如何使用unarchivedObjectOfClass解压缩数据:fromData:error:?

问题描述 投票:2回答:1

我正在使用unarchiveObjectWithDataNSUserDefaults解压缩数据并且它运​​行良好,但它在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];

我收到“数据无法读取,因为格式不正确”。

ios objective-c ios12
1个回答
1
投票

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];
© www.soinside.com 2019 - 2024. All rights reserved.