我正在使用unarchiveObjectWithData
从NSUserDefaults
解压缩数据并且它运行良好,但它在iOS 12.0中已被弃用。 Xcode建议使用unarchivedObjectOfClass:fromData:error:
,但这种方法不起作用。
我有一个班级的对象数组来取消归档。
我试图使用unarchivedObjectOfClass:fromData:error:
,unarchivedObjectOfClasses:fromData:error:
与所有类(NSArray,NSString,MYCLASS ..)
作品
NSArray *stored = [NSKeyedUnarchiver unarchiveObjectWithData:data];
才不是:
NSArray *stored = [NSKeyedUnarchiver unarchivedObjectOfClass:[MYCLASS class] fromData:data error:&error];
我收到“数据无法读取,因为格式不正确”。
unarchivedObjectOfClass:fromData:error
似乎很无人问津,但我已经弄清楚了。在您的情况下,因为您正在取消归档NSArray
并假设数组的内容是标准类,如NSString
,那么这应该适合您:
NSArray *stored = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:&error];
然而,我正在取消归档自定义对象PurchasedSubscription
,如果你的NSArray
包含任何自定义类,这也适用...首先,从方法到unarchive的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];