【问题标题】:archivedDataWithRootObject: always returns "nil"archivedDataWithRootObject:总是返回“nil”
【发布时间】:2021-04-01 08:38:22
【问题描述】:

我有一个名为Person 的类并创建了一个Person instance“人”。

Person *person = [Person personWithName:@"Kyle", andAge:15];

然后我尝试使用方法archivedDataWithRootObject:requiringSecureCoding:error:对其进行编码。

NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person 
                                      requiringSecureCoding:YES error:nil];

但是,personData 始终返回 nil。我错过了什么吗?

Person.h

@interface Person : NSObject<NSSecureCoding>
@property (strong, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger age;
+ (instancetype)personWithName:(NSString *)name andAge:(NSInteger)age;
@end

Person.m

@implementation Person
+ (instancetype)personWithName:(NSString *)name andAge:(NSInteger)age{
    Person *p = [Person new];
    p.name = name;
    p.age = age;
    return p;
}
+ (BOOL)supportsSecureCoding {
    return YES;
}
- (id)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder]; // error: No visible @interface for 'NSObject' declares the selector 'initWithCoder'
    return self;
}
@end

更新(在 .m 中实现 +supportsSecureCoding 之后):

类“Person”有一个支持安全编码的超类,但是 'Person' 覆盖 -initWithCoder: 并且不覆盖 +支持安全编码。该类必须实现 +supportsSecureCoding 并返回 YES 以验证其 -initWithCoder: 的实现是否为 安全编码兼容。

【问题讨论】:

  • 如果您使用error 参数而不是传递nil,它是否会提供有关失败原因的更多信息?另外,控制台中是否有错误消息? PersonNSCoding(和NSSecureCoding)是否符合要求?
  • @Larme 它告诉我“这个解码器只会解码采用 NSSecureCoding 的类。类'Person'不采用它。”然后我implement +supportsSecureCoding in .m,但又得到一个错误(已在描述中更新)。
  • NSKeyedArchiver 链接到NSCoding,否则,它不知道如何将该类转换为NSData 并反转。现在,有了“安全的东西”,几乎是一样的。如错误消息中所述,您需要覆盖 supportsSecureCoding 以返回 YES。这很明确。不?你是怎么写的?可以分享一下代码吗?
  • @Larme 已发布代码。 TIA:)
  • 你没有写initWithCoder

标签: objective-c nskeyedarchiver


【解决方案1】:

出了什么问题:Person 不符合 NSSecureCoding。如果您曾经玩过使用 NSKeyedArchiver 将自定义类存档到数据中,这是您首先想到的(如果是老开发人员,他/她会说 NSCoding,但那是“几乎相同”,相同的逻辑)。 这有什么关系?这只是如何将Person 转换为NSData 并反转。逻辑是什么?你想保存它的属性吗?如何?等等。

但是,你作为开发者最大的错误就是完全忽略了错误参数!

NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person 
                                      requiringSecureCoding:YES error:nil];

==>

NSError *archiveError
NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person 
                                      requiringSecureCoding:YES
                                      error:& archiveError];
if (archiveError) {
    NSLog(@"Ooops, got error while archiving: %@", archiveError);
}

那么错误会表明它确实缺少NSSecureCoding 合规性

查看Archives and Serializations Programming Guide: Encoding and Decoding Objects的文档,你会看到如何实现initWithCoder:(从NSDataPerson)和encodeWithCoder:(从PersonNSData)。

应用于您的班级(并将其添加到符合性:例如@interface Person : NSObject&lt; NSSecureCoding &gt;):

- (void) encodeWithCoder:(NSCoder *)encoder { 
    [encoder encodeObject:_name forKey:@"name"]; 
    [encoder encodeInteger:_age forKey:@"age"]; 
} 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    if (self) { 
        _name = [coder decodeObjectForKey:@"name"]; 
        _age = [coder decodeIntegerForKey:@"age"]; 
    } 
    return self; 
}

+ (BOOL)supportsSecureCoding {
    return YES;
}

注意strings key("name"&"age"编码/解码需要相同,可以使用const等)

【讨论】:

    猜你喜欢
    • 2014-05-24
    • 2017-03-28
    • 2015-03-05
    • 2014-08-25
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多