自己电脑做网站需要备案吗2,wordpress大括号,小企业网站建设地点,移动互联网开发实训报告在之前介绍的数据存储方法中#xff0c;不管是NSUserDefaults还是plist文件都不能对自定义对象进行存储#xff0c;OC提供的解归档恰好解决了这个问题
本片文章对 iOS13 以后的版本 归档和解档 进行介绍。老版本的解归档见这篇文章#xff1a;【iOS】文件#xff08;对象数…在之前介绍的数据存储方法中不管是NSUserDefaults还是plist文件都不能对自定义对象进行存储OC提供的解归档恰好解决了这个问题
本片文章对 iOS13 以后的版本 归档和解档 进行介绍。老版本的解归档见这篇文章【iOS】文件对象数据的归档和解档参考这篇文章对比学习会对解归档有更好的理解 目录 简介自定义对象的单个对象归档、解档多个对象解档归档嵌套类复合类解档 Success注意MJExtension库JSONModel、YYModel 简介
在iOS中对象的序列化和反序列化分别使用NSKeyedArchiver和NSKeyedUnarchiver两个类我们可以把一个类对象进行序列化然后保存到文件中使用时再读取文件把内容反序列化出来。这个过程通常也被称为 对象的编码归档和解码解档
归档 — 将对象以文件二进制数据的形式保存到磁盘上中也称序列化持久化解档 — 使用时从磁盘上读取该文件的保存路径从而读取文件的内容也称反序列化
归档一般保存自定义对象、自定义对象数组由于自定义对象不具有归档的性质所以只有遵循了NSCoding协议的类才可以归档 由于决大多数支持存储数据的Foundation和Cocoa Touch类都遵循了NSCoding协议因此对于大多数OC提供的类来说归档相对而言还是比较容易实现的。
对象归档的文件是保密的在磁盘上无法查看文件中的内容而属性列表是明文的可以查看。通过文件归档产生的文件是不可见的如果打开归档文件的话内容是乱码的ta不同于属性列表和plist文件是可见的正因为不可见的缘故使得这种持久性的数据保存更有可靠性
自定义对象的单个对象归档、解档
iOS 13中需要支持NSSecureCoding 协议父协议为NSCoding才能支持归档
自定义一个Person类并实现NSCoding 协议的方法
interface Person : NSObject NSSecureCodingproperty (nonatomic, copy)NSString* name;
property (nonatomic, assign)int age;
property (nonatomic, assign)double weight;endimplementation Person//NSCoder是一个抽象类
//归档的协议方法
//将归档对象序列化
- (void)encodeWithCoder:(NSCoder *)coder {[coder encodeObject: self.name forKey: name];[coder encodeInt: self.age forKey: age];[coder encodeDouble: self.weight forKey: weight];
}//解档的协议方法
//将解档对象反序列化
- (instancetype)initWithCoder:(NSCoder *)coder {self [super init];if (self) {self.name [coder decodeObjectForKey: name];self.age [coder decodeIntForKey: age];self.weight [coder decodeDoubleForKey: weight];}return self;
}end//NSSecureCoding的协议方法(BOOL)supportsSecureCoding {return YES;
}
初始化待归档对象并进行归档 (nullable NSData *)archivedDataWithRootObject:(id)object requiringSecureCoding:(BOOL)requiresSecureCoding error:(NSError **)error; Person* person [[Person alloc] init];person.name XY;person.age 20;person.weight 125.0;//归档成二进制数据流NSError* error;NSData* data1 [NSKeyedArchiver archivedDataWithRootObject: person requiringSecureCoding: YES error: error];if (error) {NSLog(归档错误%, error);return 0;}//写入指定路径一般写入到沙盒这里方便演示存到一个新的文件夹[data1 writeToFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver atomically: YES];Person对象被序列化后就会被保存在下方的文件中但无法直接打开
通过终端命令打开后可以看到内容是经过加密的保证了数据的安全性
开始解档 (nullable id)unarchivedObjectOfClass:(Class)cls fromData:(NSData *)data error:(NSError **)error; //解档此二进制数据error nil;NSData* data2 [NSData dataWithContentsOfFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver];Person* unarchiverPerson (Person *)[NSKeyedUnarchiver unarchivedObjectOfClass: [Person class] fromData: data2 error: error];if (error) {NSLog(解档错误%, error);}NSLog(unarchiverPerson%, unarchiverPerson);多个对象解档归档
将多个对象归档在同一个文件中
初始化待归档对象并进行归档
Person* person1 [[Person alloc] init];
person1.name XY;
person1.age 20;
person1.weight 125.0;
Dog* dog1 [[Dog alloc] init];
dog1.name Bruce;
person1.dog dog1; Person* person2 [[Person alloc] init];
person2.name Jacky;
person2.age 21;
person2.weight 130.0;
Dog* dog2 [[Dog alloc] init];
dog2.name Oudy;
person2.dog dog2;//创建归档对象
NSKeyedArchiver* archiver [[NSKeyedArchiver alloc] initRequiringSecureCoding: NO];//进行归档编码操作
[archiver encodeObject: person1 forKey: personOne];
[archiver encodeObject: person2 forKey: personTwo];//将归档序列化后的数据写入指定文件中
[archiver.encodedData writeToFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver atomically: YES];//结束归档
[archiver finishEncoding];依次解档
//解档
NSData* data [NSData dataWithContentsOfFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver];
NSKeyedUnarchiver* unarchiver [[NSKeyedUnarchiver alloc] initForReadingFromData: data error: nil];
unarchiver.requiresSecureCoding NO;Person* unchiverPerson1 [unarchiver decodeObjectForKey: personOne];
NSLog(% %d %lf %, unchiverPerson1.name, unchiverPerson1.age, unchiverPerson1.weight, unchiverPerson1.dog.name);
Person* unchiverPerson2 [unarchiver decodeObjectForKey: personTwo];
NSLog(% %d %lf %, unchiverPerson2.name, unchiverPerson2.age, unchiverPerson2.weight, unchiverPerson2.dog.name);嵌套类复合类
现对于Person类设置一个自定义对象dog属性那么这个内层的Dog类也需要实现NSSecureCoding 协议否则程序会崩溃 上面也提到过OC提供的类比如这里的name已经遵循了此协议因此无需手动操作但自定义的Dog类要手动添加协议函数
interface Dog : NSObject NSSecureCodingproperty (nonatomic, strong)NSString* name;end- (void)encodeWithCoder:(NSCoder *)coder {[coder encodeObject: self.name forKey: dogName];
}- (instancetype)initWithCoder:(NSCoder *)coder {self [super init];if (self) {self.name [coder decodeObjectForKey: dogName];}return self;
} (BOOL)supportsSecureCoding {return YES;
}以下是复合类解归档完整代码
#import Foundation/Foundation.h
#import Person.h
#import Dog.hint main(int argc, const char * argv[]) {autoreleasepool {Person* person1 [[Person alloc] init];person1.name XY;person1.age 20;person1.weight 125.0;Dog* dog1 [[Dog alloc] init];dog1.name Bruce;person1.dog dog1;Person* person2 [[Person alloc] init];person2.name Jacky;person2.age 21;person2.weight 130.0;Dog* dog2 [[Dog alloc] init];dog2.name Oudy;person2.dog dog2;//创建归档对象NSKeyedArchiver* archiver [[NSKeyedArchiver alloc] initRequiringSecureCoding: NO];//进行归档操作[archiver encodeObject: person1 forKey: personOne];[archiver encodeObject: person2 forKey: personTwo];//将归档序列化后的数据写入指定文件中[archiver.encodedData writeToFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver atomically: YES];//结束归档[archiver finishEncoding];//解档NSData* data [NSData dataWithContentsOfFile: /Users/jakey/Desktop/CS/Xcode/NSKeyedArchiverTest/test.archiver];NSKeyedUnarchiver* unarchiver [[NSKeyedUnarchiver alloc] initForReadingFromData: data error: nil];unarchiver.requiresSecureCoding NO;Person* unchiverPerson1 [unarchiver decodeObjectForKey: personOne];NSLog(% %d %lf %, unchiverPerson1.name, unchiverPerson1.age, unchiverPerson1.weight, unchiverPerson1.dog.name);Person* unchiverPerson2 [unarchiver decodeObjectForKey: personTwo];NSLog(% %d %lf %, unchiverPerson2.name, unchiverPerson2.age, unchiverPerson2.weight, unchiverPerson2.dog.name);return 0;
}运行结果如下 解档 Success
注意
如果需要归档的类是某个自定义类的子类时就需要在归档和解档之前实现父类的解档和归档方法[super encodeWithCoder: coder];和[super initWithCoder: coder]; MJExtension库JSONModel、YYModel
其实还可以使用MJExtension第三方库实现解归档这样就可以不用写复杂的NSCoding协议只需要一行代码调用写好的宏MJExtensionCodingImplementation就可以实现
MJExtension也和JSONModel、YYModel一样支持 JSON数据-Model 的转换同时也支持解归档它们在代码量级上、性能优化上各有优缺点详见这篇文章
【YYModel,MJExtension,JSONModel对比】
具体的学习小编日后了解