如何解决NSSecureCoding:将 UIView 写入磁盘
是否可以使用 NSSecureCoding 将 UIView 写入磁盘。以下代码导致错误。
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object requiringSecureCoding:YES error:&error];
错误:无法写入数据,因为它的格式不正确。
我们还尝试了以下方法:
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
[archiver encodeObject:view forKey:@"view"];
[archiver finishEncoding];
错误:这个解码器只会解码采用 NSSecureCoding 的类。 'UIView' 类不采用它。
解决方法
NSSecureCoding,除了NSCoding的要求,简单的要求类实现一个类函数+(BOOL)supportsSecureCoding。 UIView 已经支持 NSCoding 并且似乎它不符合 NSSecureCoding 可能是一个疏忽; Xcode 调试器会发出有关非 NSSecureCoding 序列化调用在不久的将来消失的警告。
您可以使用类别将类函数添加到 UIView:
@interface UIView(SecureCoding)<NSSecureCoding>
@end
@implementation UIView(SecureCoding)
+ (BOOL)supportsSecureCoding {
return TRUE;
}
@end
正如评论中指出的那样,这并不意味着您可以使用 NSKeyedUnarchiver 进行反序列化,因为 UIViews 似乎并不打算以这种方式进行序列化。我猜他们支持序列化的主要原因是用于 xibs/nibs/storyboards。下面是一个 UIView 序列化示例,它确实有效,但使用了私有 API,因此仅用于说明目的:
添加声明以访问未发布的 API:
/* Warning: Unpublished APIs!*/
@interface UINibEncoder : NSCoder
- initForWritingWithMutableData:(NSMutableData*)data;
- (void)finishEncoding;
@end
@interface UINibDecoder : NSCoder
- initForReadingWithData:(NSData *)data error:(NSError **)err;
@end
序列化/反序列化:
/* This does NOT work */
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:NO];
[archiver encodeObject:object forKey:@"view"];
[archiver finishEncoding];
data = [archiver encodedData];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
/* error: 'UIBackgroundColor' was of unexpected class 'UIColor' */
data = [unarchiver decodeObjectForKey:@"view"];
/* This DOES work,but don't use it in an app you plan to publish */
NSMutableData *mData = [NSMutableData new];
UINibEncoder *encoder = [[UINibEncoder alloc] initForWritingWithMutableData:mData];
[encoder encodeObject:object forKey:@"view"];
[encoder finishEncoding];
UINibDecoder *decoder = [[UINibDecoder alloc] initForReadingWithData:mData error:&error];
NSObject *myView = [decoder decodeObjectForKey:@"view"];
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。