archivedDataWithRootObject:始终 returns "nil"
archivedDataWithRootObject: always returns "nil"
我有一个名为 Person
的 class 并创建了一个 Person instance
“人”。
Person *person = [Person personWithName:@"Kyle", andAge:15];
然后我尝试使用方法archivedDataWithRootObject:requiringSecureCoding:error:
对其进行编码。
NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person
requiringSecureCoding:YES error:nil];
但是,personData
总是returnsnil
。我错过了什么吗?
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
Update(在 .m 中实现 +supportsSecureCoding 之后):
Class 'Person' has a superclass that supports secure coding, but
'Person' overrides -initWithCoder: and does not override
+supportsSecureCoding. The class must implement +supportsSecureCoding and return YES to verify that its implementation of -initWithCoder: is
secure coding compliant.
出了什么问题:Person
不符合 NSSecureCoding
标准。如果你玩过 Archiving Custom Class into Data with NSKeyedArchiver(如果是老开发者,he/she 会说 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:
(从 NSData
到 Person
)和 encodeWithCoder:
(从 Person
到 NSData
).
应用于您的 class(并将其添加到符合性中:例如 @interface Person : NSObject< NSSecureCoding >
):
- (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;
}
注意字符串键("name"
& "age"
需要与 encode/decode 相同,可以使用 const 等)
我有一个名为 Person
的 class 并创建了一个 Person instance
“人”。
Person *person = [Person personWithName:@"Kyle", andAge:15];
然后我尝试使用方法archivedDataWithRootObject:requiringSecureCoding:error:
对其进行编码。
NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person
requiringSecureCoding:YES error:nil];
但是,personData
总是returnsnil
。我错过了什么吗?
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
Update(在 .m 中实现 +supportsSecureCoding 之后):
Class 'Person' has a superclass that supports secure coding, but 'Person' overrides -initWithCoder: and does not override +supportsSecureCoding. The class must implement +supportsSecureCoding and return YES to verify that its implementation of -initWithCoder: is secure coding compliant.
出了什么问题:Person
不符合 NSSecureCoding
标准。如果你玩过 Archiving Custom Class into Data with NSKeyedArchiver(如果是老开发者,he/she 会说 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:
(从 NSData
到 Person
)和 encodeWithCoder:
(从 Person
到 NSData
).
应用于您的 class(并将其添加到符合性中:例如 @interface Person : NSObject< NSSecureCoding >
):
- (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;
}
注意字符串键("name"
& "age"
需要与 encode/decode 相同,可以使用 const 等)