星落辰嶼月似鈎
兩岸茫茫路成霜
預祝中秋快樂!
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmL4kTM4BDMz0iMvwVOw8CX1EDMy8CXzRWYvxGc19CX05WZ052bj1Cc39CXQ9EVvwFMxEjL14CO2EjLykTMvw1LcpDc0RHaiojIsJye.jpg)
(圖取自百度圖庫)
對象歸檔是一種序列化方式,有的時候我們為了便于資料傳輸,我們會将歸檔對象序列化為一個檔案,使用的時候再通過反歸檔将資料恢複到對象中。對象歸檔可以實作資料持久化,不過在大量資料和頻繁讀寫的情況下,不适用。雖然沒有plist快捷,但是可以将自定義對象寫入檔案,可以歸檔集合類,是以無論添加多少對象,将對象寫入磁盤的方式是相同的,并不會增加工作量。
對象歸檔:使用NSKeyedArichiver進行歸檔,使用NSKeyedUnarchiver進行反歸檔,另外,歸檔的對象必須是基本資料類型或實作了NSCoding協定的類的某個執行個體。
在此我們模拟一個場景,點選Home鍵退出時對資料進行歸檔,恢複時進行解檔。畫面如下(畫面連接配接不再贅述,參照以前站點):
我們分開講解代碼,單個對象歸檔、多個對象歸檔以及自定義對象歸檔。
首先歸檔檔案路徑我單獨寫了一個函數擷取:
-(NSString *)archiverPath{
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *archiverPath = [documentPath stringByAppendingPathComponent:@"archive.archiver"];
return archiverPath;
}
另外在viewDidLoad方法中注冊監聽(點選Home鍵時會發送名為UIApplicationWillResignActiveNotification的通知(有點像安卓的廣播)):
//applicationWillResignActive:方法自定義
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
單個對象歸檔:
對單個對象進行歸檔最簡單。利用NSKeyedArchiver的archiveRootObject:toFile:類方法歸檔,NSKeyedUnarchiver 的unarchiveObjectWithFile:類方法反歸檔;不過,一個檔案隻能存儲一個對象。
- (void)viewDidLoad {
[super viewDidLoad];
NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果檔案存在,反歸檔。
if ([fileManager fileExistsAtPath:[self archiverPath]]){
// NSKeyedUnarchiver的unarchiveObjectWithFile:類方法,解檔
NSString *content = [NSKeyedUnarchiver unarchiveObjectWithFile:[self archiverPath]];
self._userName.text = content == nil ? @"" : content;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}
// 點選Home鍵時歸檔。
-(void)applicationWillResignActive:(NSNotification *)notify{
// NSKeyedArchiver的archiveRootObject:toFile:類方法,歸檔。将self._userName.text對象歸檔到archive.archiver檔案,傳回值為歸檔是否成功。
// 這種方式可以對字元串、數字等進行歸檔,當然也可以對NSArray與NSDictionary進行歸檔。
BOOL result = [NSKeyedArchiver archiveRootObject:self._userName.text toFile:[self archiverPath]];
if (!result) {
NSLog(@"歸檔失敗!");
}
}
多個對象歸檔:
多個對象歸檔還是使用NSKeyedArchiver 和NSKeyedUnarchiver,不過寫入和讀取的方式變了,這裡是利用NSMutableData的writeToFile:atomically:方法。
- (void)viewDidLoad {
[super viewDidLoad];
NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果檔案存在,反歸檔。
if ([fileManager fileExistsAtPath:[self archiverPath]])
// 利用NSData讀取歸檔資料
NSMutableData *unarchiveData = [NSMutableData dataWithContentsOfFile:[self archiverPath]];
// 建立依賴于NSData對象的NSKeyedUnarchiver反歸檔對象,用于反歸檔
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiveData];
// key和歸檔時一緻。
self._userName.text = [unarchiver decodeObjectForKey:@"UserName"];
self._address.text = [unarchiver decodeObjectForKey:@"Address"];
self._mail.text = [unarchiver decodeObjectForKey:@"Mail"];
[self._datePicker setDate:[unarchiver decodeObjectForKey:@"Birthday"]];
// 結束反歸檔(不要遺漏)
[unarchiver finishDecoding];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}
// 點選Home鍵時歸檔。
-(void)applicationWillResignActive:(NSNotification *)notify{
// 建立依賴于NSMutableData對象的NSKeyedArchiver歸檔對象。
NSMutableData *archiveData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];
//對需要歸檔的基本資料類型進行歸檔。反歸檔時所用key和這裡設定的key一緻。
[archiver encodeObject:self._userName.text forKey:@"UserName"];
[archiver encodeObject:self._address.text forKey:@"Address"];
[archiver encodeObject:self._mail.text forKey:@"Mail"];
[archiver encodeObject:self._datePicker.date forKey:@"Birthday"];
// 結束歸檔(不要遺漏)
[archiver finishEncoding];
// 将NSData對象寫入檔案。
[archiveData writeToFile:[self archiverPath] atomically:YES];
}
自定義對象歸檔:
一般是實體類,自定義對象必須實作NSCoding協定,實作該協定的encodeWithCoder:和initWithCoder:方法,其實和多對象歸檔類似,隻不過将這些對象放到了一個自定義類裡去實作
這裡我建立了UserInfo類,繼承自NSObject,實作NSCoding協定。
@interface UserInfo : NSObject<NSCoding>
@property(nonatomic,strong) NSString* userName;
@property(nonatomic,strong) NSString* address;
@property(nonatomic,strong) NSString* mail;
@property(nonatomic,strong) NSDate* birthday;
@end
@implementation UserInfo
@synthesize userName = _userName;
@synthesize address = _address;
@synthesize mail = _mail;
@synthesize birthday = _birthday;
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_userName forKey:@"UserName"];
[aCoder encodeObject:_address forKey:@"Address"];
[aCoder encodeObject:_mail forKey:@"Mail"];
[aCoder encodeObject:_birthday forKey:@"Birthday"];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
_userName = [aDecoder decodeObjectForKey:@"UserName"];
_address = [aDecoder decodeObjectForKey:@"Address"];
_mail = [aDecoder decodeObjectForKey:@"Mail"];
_birthday = [aDecoder decodeObjectForKey:@"Birthday"];
}
return self;
}
@end
這樣在外面,我們隻需要歸檔反歸檔UserInfo對象就可以了。
- (void)viewDidLoad {
[super viewDidLoad];
NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果檔案存在,反歸檔。
if ([fileManager fileExistsAtPath:[self archiverPath]]){
// 利用NSData讀取歸檔資料
NSMutableData *unarchiveData = [NSMutableData dataWithContentsOfFile:[self archiverPath]];
// 建立依賴于NSData對象的NSKeyedUnarchiver反歸檔對象,用于反歸檔
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiveData];
UserInfo *userInfo = [unarchiver decodeObjectForKey:@"UserInfo"];
self._userName.text = userInfo.userName;
self._address.text = userInfo.address;
self._mail.text = userInfo.mail;
[self._datePicker setDate:userInfo.birthday];
// 結束反歸檔(不要遺漏)
[unarchiver finishDecoding];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// 點選Home鍵時歸檔。
-(void)applicationWillResignActive:(NSNotification *)notify{
// 建立依賴于NSMutableData對象的NSKeyedArchiver歸檔對象。
NSMutableData *archiveData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];
UserInfo *userInfo = [[UserInfo alloc] init];
userInfo.userName = self._userName.text;
userInfo.address = self._address.text;
userInfo.mail = self._mail.text;
userInfo.birthday = self._datePicker.date;
[archiver encodeObject:userInfo forKey:@"UserInfo"];
// 結束歸檔(不要遺漏)
[archiver finishEncoding];
// 将NSData對象寫入檔案。
[archiveData writeToFile:[self archiverPath] atomically:YES];
}