简体   繁体   English

如何将 NSKeyedUnarchiver unarchiveObjectWithData 更新为 NSKeyedUnarchiver unarchivedObjectOfClass:[fromData:error:

[英]How to update NSKeyedUnarchiver unarchiveObjectWithData to NSKeyedUnarchiver unarchivedObjectOfClass:[fromData:error:

My app currently uses this deprecated function:我的应用程序目前使用这个已弃用的 function:

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

To update, I've converted to this:要更新,我已转换为:

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

The data was originally encoded like this:数据最初是这样编码的:

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

What could be causing the IF statement to return FALSE using the newer code?什么可能导致 IF 语句使用较新的代码返回 FALSE?

Please note that I am concerned primarily with reading existing data stored prior to deprecating the Archiving functions.请注意,我主要关心的是在弃用存档功能之前读取存储的现有数据。 Simply changing to the newer functions does not resolve the issue.简单地更改为较新的功能并不能解决问题。

Interesting question.有趣的问题。 I've been supporting iOS 10.0 so I haven't encountered such issue until I saw this.我一直在支持 iOS 10.0,所以在看到这个之前我还没有遇到过这样的问题。 I was tinkering for an hour and I successfully found the issue.我修修补补了一个小时,我成功地找到了问题。

What could be causing the IF statement to return FALSE using the newer code?什么可能导致 IF 语句使用较新的代码返回 FALSE?

It's because your unarchivedObject object is nil !这是因为你的unarchivedObject object 是nil

If you use the parameter error in the new method, you would see an error like this:如果您在新方法中使用参数error ,您会看到如下错误:

Error Domain=NSCocoaErrorDomain Code=4864 "This decoder will only decode classes that adopt NSSecureCoding. Class 'QTPerson' does not adopt it."错误域=NSCocoaErrorDomain Code=4864 "此解码器将仅解码采用 NSSecureCoding 的类。Class 'QTPerson' 不采用它。" UserInfo={NSDebugDescription=This decoder will only decode classes that adopt NSSecureCoding. UserInfo={NSDebugDescription=此解码器只会解码采用 NSSecureCoding 的类。 Class 'QTPerson' does not adopt it. Class 'QTPerson' 不采用。

But how do we get the correct value for this unarchivedObject and not nil?但是我们如何获得这个unarchivedObject而不是 nil 的正确值呢? It would take a couple of steps.这需要几个步骤。

First off, make your model/class conform to <NSCoding, NSSecureCoding>首先,让你的模型/类符合<NSCoding, NSSecureCoding>

Example: QTPerson.h示例: 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

And then implement the protocol methods:然后实现协议方法:

QTPerson.m 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

And then when archiving an object, you would want to pass YES to the parameter requiringSecureCoding , like so:然后在归档 object 时,您requiringSecureCodingYES传递给参数 requiresSecureCoding ,如下所示:

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

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

Lastly, when unarchiving, just do what you did correctly, like so:最后,在取消归档时,只需执行正确的操作,如下所示:

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

Voila!瞧! You'll get nonnull object unarchivedObject , hence the TRUE/YES value you're looking for!您将获得非空 object unarchivedObject ,因此您正在寻找 TRUE/YES 值!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM