我正在使用unarchiveObjectWithData
来对NSUserDefaults
中的数据进行取消存档,并且运行良好,但是在iOS 12.0中已弃用。
Xcode建议使用unarchivedObjectOfClass:fromData:error:
,但此方法无效。
我有一个要取消存档的类对象数组。
我尝试对所有类(NSArray,NSString,MYCLASS ..)也使用unarchivedObjectOfClass:fromData:error:
和unarchivedObjectOfClasses:fromData:error:
作品
NSArray *stored = [NSKeyedUnarchiver unarchiveObjectWithData:data];
不是:
NSArray *stored = [NSKeyedUnarchiver unarchivedObjectOfClass:[MYCLASS class] fromData:data error:&error];
我收到“数据格式不正确,无法读取。”
答案 0 :(得分:1)
unarchivedObjectOfClass:fromData:error
似乎还没有记载,但我已经弄清楚了。
在您要解压缩NSArray
并假设数组内容是NSString
之类的标准类的情况下,这应该对您有用:
NSArray *stored = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:&error];
但是我取消了对自定义对象PurchasedSubscription
的归档,如果您的NSArray
包含任何自定义类,这也适用。
首先,从方法到取消归档的objectOfClass
必须是您期望得到的结果的类。
PurchasedSubscription *purchasedSubscription = [NSKeyedUnarchiver unarchivedObjectOfClass:PurchasedSubscription.class fromData:data error:&error];
接下来,您的自定义类需要符合NSSecureCoding
,因此请将其添加到类的接口。我假设您已经实现了NSCoding
。
@interface PurchasedSubscription : NSObject <NSCoding, NSSecureCoding>
@end
接下来,您的班级必须重写supportsSecureCoding
以确认其受支持
+ (BOOL)supportsSecureCoding
{
return YES;
}
接下来,在您的initWithCoder:
方法中,解码每个属性时,您需要使用decodeObjectOfClass:key:
而不是decodeObjectForKey
,再次将Class
参数设置为被解码。
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder
{
self = [self init];
if (self)
{
ReceiptInfo *receiptInfo = [aDecoder decodeObjectOfClass:[ReceiptInfo class] forKey:@"receiptInfo"];
return [self initWithReceiptInfo:receiptInfo];
}
return self;
}
正如您在此处看到的那样,该类还解码了另一个自定义类ReceiptInfo
,因此我必须对该类重复此过程才能使所有功能正常工作。
现在使用时
PurchasedSubscription *purchasedSubscription = [NSKeyedUnarchiver unarchivedObjectOfClass:PurchasedSubscription.class fromData:data error:&error];
它通过安全地解码PurchasedSubscription
类来安全地解码ReceiptInfo
类,因为它在每一步都知道在解码它之前该类的类型。
相反NSEncoding
上的注释。您需要使用方法
archivedDataWithRootObject:requiringSecureCoding:error:
代替
archivedDataWithRootObject:
使用此方法,您无需传递对象类,而可以传递实际的对象。 就我而言,我像这样创建对象
PurchasedSubscription *validSub = [[PurchasedSubscription alloc] initWithReceiptInfo:latestReceipt];
然后像这样编码
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:validSub requiringSecureCoding:YES error:&error];
答案 1 :(得分:1)
我遇到了一个问题,并按照@Darren的答案进行操作,但是 unarchivedObjectOfClass 返回 nil ! :(
所以我尝试了很多变化,发现唯一成功的方法就是我的情况:
supportsSecureCoding 属性必须为
和
NSArray<MyClassConformedToNSObject_NSCoding_NSSecureCoding *> *arrayOfCustomObjects = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSObject class] fromData:data error:&error];