【问题标题】:How to update NSKeyedUnarchiver unarchiveObjectWithData to NSKeyedUnarchiver unarchivedObjectOfClass:[fromData:error:如何将 NSKeyedUnarchiver unarchiveObjectWithData 更新为 NSKeyedUnarchiver unarchivedObjectOfClass:[fromData:error:
【发布时间】:2019-09-21 18:39:34
【问题描述】:

我的应用目前使用这个已弃用的功能:

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?

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

【问题讨论】:

    标签: ios objective-c nscoder nsarchiving


    【解决方案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
    

    然后实现协议方法:

    QTPerson.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!");
    }
    

    瞧!您将获得非空对象 unarchivedObject,因此您正在寻找 TRUE/YES 值!

    【讨论】:

    • 感谢代码/研究,但是在实施之后,我在读取现有数据时仍然得到一个空的未归档对象 - 这是真正的问题。我可以删除此应用更新的现有数据并重新开始,但是该应用的现有用户将丢失他们的数据,我不希望这样做。
    • @wayneh 你找到解决方案了吗?
    • @DavidvanDugteren 不,我还没有解决这个问题。目前我已经从 App Store 中提取了我的应用程序。
    猜你喜欢
    • 2019-08-15
    • 2016-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    相关资源
    最近更新 更多