归档是指一种形式的序列化,专门编写用于保存数据的任何对象都应该支持归档。使用对模型对象进行归档的技术可以轻松将复杂的对象写入文件,然后再从中读取它们。
只要在类中实现的每个属性都是标量或者都是遵循NSCoding协议的某个类的实例,你就可以对整个对象进行完全归档。大多数的Foundation和Cocoa Touch类 都遵NSCoding协议,所以对于有大多数类来说,归档不太难。
遵循NSCoding协议:
NSCoding声明了两个方法,
- (void)encodeWithCoder:(NSCoder *)aCoder;和- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
第一个是 将对象编码到归档中,第二个则是对归档解码,来创建一个对象。
在BIDFourLines中:
#import <Foundation/Foundation.h> @interface BIDFourLines : NSObject <NSCoding, NSCopying> @property (copy, nonatomic) NSArray *lines; @end#import "BIDFourLines.h" static NSString * const kLinesKey = @"kLinesKey"; @implementation BIDFourLines #pragma mark - Coding - (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { self.lines = [aDecoder decodeObjectForKey:kLinesKey]; } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder; { [aCoder encodeObject:self.lines forKey:kLinesKey]; } #pragma mark - Copying - (id)copyWithZone:(NSZone *)zone; { BIDFourLines *copy = [[[self class] allocWithZone:zone] init]; NSMutableArray *linesCopy = [NSMutableArray array]; for (id line in self.lines) { [linesCopy addObject:[line copyWithZone:zone]]; } copy.lines = linesCopy; return copy; } @end
注:上面遵循了NSCopying协议,遵循NSCopying协议对于任何模型对象来说都是非常好的事情,NSCopying协议中,有一个copyWithZone方法,可以用来复制对象。
在BIDViewController中:
#import "BIDViewController.h" #import "BIDFourLines.h" static NSString * const kRootKey = @"kRootKey"; @interface BIDViewController () @property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *lineFields; @end @implementation BIDViewController - (NSString *)dataFilePath { NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; return [documentsDirectory stringByAppendingPathComponent:@"data.archive"]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *filePath = [self dataFilePath]; //如果存在归档 if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath]; NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; //解档 BIDFourLines *fourLines = [unarchiver decodeObjectForKey:kRootKey]; [unarchiver finishDecoding]; for (int i = 0; i < 4; i++) { UITextField *theField = self.lineFields[i]; theField.text = fourLines.lines[i]; } } //后台通知 UIApplication *app = [UIApplication sharedApplication]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app]; } //进入后台时 归档 - (void)applicationWillResignActive:(NSNotification *)notification { NSString *filePath = [self dataFilePath]; BIDFourLines *fourLines = [[BIDFourLines alloc] init]; fourLines.lines = [self.lineFields valueForKey:@"text"]; NSMutableData *data = [[NSMutableData alloc] init]; NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; [archiver encodeObject:fourLines forKey:kRootKey]; [archiver finishEncoding]; [data writeToFile:filePath atomically:YES]; }