2

我的应用程序当前使用此已弃用的功能:

id unarchivedObject=[NSKeyedUnarchiver unarchiveObjectWithData:codedData];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns TRUE when reading existing user data.
} 

要更新,我已转换为:

id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[NSDictionary class] fromData:codedData error:nil];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns FALSE when reading existing user data.
}

数据最初是这样编码的:

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:text forKey:@"text"];
}
-(instancetype)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        text=[decoder decodeObjectForKey:@"text"];
}

什么可能导致 IF 语句使用较新的代码返回 FALSE?

请注意,我主要关心的是在弃用存档功能之前读取存储的现有数据。简单地更改为较新的功能并不能解决问题。

4

1 回答 1

1

有趣的问题!我一直在支持 iOS 10.0,所以在看到这个之前我还没有遇到过这样的问题。我修修补补了一个小时,我成功地找到了问题。

什么可能导致 IF 语句使用较新的代码返回 FALSE?

这是因为你的unarchivedObject对象是nil

如果您error在新方法中使用该参数,您会看到如下错误:

" Error Domain=NSCocoaErrorDomain Code=4864 "这个解码器只会解码采用 NSSecureCoding 的类。类 'QTPerson' 不采用它。" UserInfo={NSDebugDescription=此解码器只会解码采用 NSSecureCoding 的类。'QTPerson' 类不采用它。

但是我们如何得到正确的值unarchivedObject而不是 nil 呢?这需要几个步骤。

首先,使您的模型/类符合<NSCoding, NSSecureCoding>

示例: QTPerson.h

#import <Foundation/Foundation.h>

@class QTPerson;

NS_ASSUME_NONNULL_BEGIN

#pragma mark - Object interfaces

@interface QTPerson : NSObject <NSCoding, NSSecureCoding>
@property (nonatomic, copy) NSString *text;
@end

NS_ASSUME_NONNULL_END

然后实现协议方法:

QTPperson.m

#import "QTPerson.h"

@implementation QTPerson

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:_text forKey:@"text"];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _text = [coder decodeObjectOfClass:[NSString class] forKey:@"text"];
    }
    return self;
}

@end

然后在归档对象时,您需要传递YES给参数requiringSecureCoding,如下所示:

QTPerson *person = [[QTPerson alloc] init];
person.text = @"Glenn";

NSData *codedData1 = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setValue:codedData1 forKey:@"boom"];

最后,在取消归档时,只需执行正确的操作,如下所示:

NSData *codedData = [[NSUserDefaults standardUserDefaults] dataForKey:@"boom"];

NSError *er;
id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[QTPerson class] fromData:codedData error:&er];

if([unarchivedObject isKindOfClass:[QTPerson class]]){
    NSLog(@"TRUE!");
} else {
    NSLog(@"FALSE!");
}

瞧!您将获得 nonnull object unarchivedObject,因此您正在寻找 TRUE/YES 值!

于 2019-09-21T20:25:03.697 回答