天天看點

Objective-C之資料持久化-對象歸檔

星落辰嶼月似鈎

兩岸茫茫路成霜

預祝中秋快樂!

Objective-C之資料持久化-對象歸檔

(圖取自百度圖庫)

對象歸檔是一種序列化方式,有的時候我們為了便于資料傳輸,我們會将歸檔對象序列化為一個檔案,使用的時候再通過反歸檔将資料恢複到對象中。對象歸檔可以實作資料持久化,不過在大量資料和頻繁讀寫的情況下,不适用。雖然沒有plist快捷,但是可以将自定義對象寫入檔案,可以歸檔集合類,是以無論添加多少對象,将對象寫入磁盤的方式是相同的,并不會增加工作量。

對象歸檔:使用NSKeyedArichiver進行歸檔,使用NSKeyedUnarchiver進行反歸檔,另外,歸檔的對象必須是基本資料類型或實作了NSCoding協定的類的某個執行個體。

在此我們模拟一個場景,點選Home鍵退出時對資料進行歸檔,恢複時進行解檔。畫面如下(畫面連接配接不再贅述,參照以前站點):

Objective-C之資料持久化-對象歸檔

我們分開講解代碼,單個對象歸檔、多個對象歸檔以及自定義對象歸檔。

首先歸檔檔案路徑我單獨寫了一個函數擷取:

-(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];

}