就像上一節我們對屬性列表的介紹,歸檔( arching) 也是指另一種形式的序列化.但強大的一點事,它是任何對象都可實現的更常規的儲存數據類型.
在進行歸檔與解檔的開發中.我們需要一起實現的,還有 NSCoding
和 NSCopying
協議,需要說明的是,標量( int 或 float)
以及大多數Foundation
和Cocoa Touch
類都遵循NSCoding
協議(有例外,如 UIImage 不遵循),因此大多數類,還是比較容易實現歸檔操作的;
1.遵循NSCoding
協議,NSCopying
協議
NSCoding
協議聲明了2個方法;一個是將對象編碼到歸檔中,另一個是對歸檔的解碼來恢復我們之前歸檔的對象,使用方法與NSUserDefaults
相似,亦可以用 KVC 對對象和原生數據類型( int 或 float)
進行編碼和解碼.
NSCopying
協議用于允許賦值對象,是的使用數據模型對象時具備較大的靈活性;
2,歸檔\解檔
歸檔:創建一個 NSKeyedArchiver
實例,用于將對象歸檔到一個 NSMutableData
實例中,此時NSMutableData
包含編碼的數據,在使用鍵/碼對需要的對象進行歸檔,最后告知完成,寫入文件系統.
解檔:也與歸檔對象步驟相似,創建一個 NSData
實例用于裝載數據,并創建一個 NSKeyedUnarchiver
實例,對數據解碼,然后使用先前的鍵進行讀取對象.最后告知程序解檔完成.
a.”linePesist”類的創建
在Xcode中,使用Single View Application模板創建一個新項目,命名為persistence2,沒錯,還是跟屬性列表一樣的應用模板。
但是需要創建一個新文件,按command+N,或者從File菜單中依次選擇New->New File。出現新建文件向導后,選擇Cocoa Touch,然后選擇Objective-C class,單擊Next,將類命名為“linePesist”,并在“Subclass of”一欄中選擇NSObject,單擊Next,再單擊Create。該類做為我們的數據模型,并且將用于存儲屬性列表應用的字典中的數據。
單擊“linePesist.h”,修改代碼如下:
#import
//遵循NSCoding、NSCopying協議
@interface linePesist : NSObject
@property (nonatomic,copy)NSArray *array;
@end
這是一個擁有數組類型的簡單數據模型,數組可以用于我們放置文本框的數據字段。
接下來,我們進行“linePesist.m”的編輯:
#import "linePesist.h"
#define CodeStr @"CodeStr"
//用于歸檔解檔的時候用的鍵名
@implementation linePesist
/* 通過遵循NSCoding和NSCoping中的方法,創建可歸檔的數據對象。*/
#pragma mark -- Coding
//編碼
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.array forKey:CodeStr];
}
//解碼
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if(self) { self.array = [aDecoder decodeObjectForKey:CodeStr];
}
return self;
}
#pragma mark -- Coping
-(id)copyWithZone:(NSZone *)zone{
linePesist *copy = [[[self class]allocWithZone:zone] init];
NSMutableArray *muAr = [[NSMutableArray alloc]init];
for(id line in self.array) {
[muAr addObject:[line copyWithZone:zone]];
}
copy.array = muAr; return copy;
}
@end
用預定義的“CodeStr”做為編碼解碼的鍵,存儲4個文本框的字符串,然后用同樣的“CodeStr”鍵進行解碼,將4個字符串復制到copyWithZone創建的linePesist對象中;
b.“ViewController”類實現
創建可歸檔的數據對象之后,我們便可以使用此來進行持久化的存儲。點擊“ViewController.m”編輯界面,并進行以下除劃掉的部分的代碼編輯
#import "ViewController.h"
#import "linePesist.h"
//導入數據模型類
#define CodeString @"CodeString"
@implementation ViewController
-(NSString *)dataFile{
NSArray *ar = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *fielpath = [ar objectAtIndex:0];
return [fielpath stringByAppendingPathComponent:@"data.archive"];
//改修后綴名,以免與屬性列表創建的文件重復,而加載成舊的的文件。 不用查字典了。。archive表歸檔
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString *filepath = [self dataFile];
NSLog(@"%@",filepath);
if([[NSFileManager defaultManager]fileExistsAtPath:filepath]) {
//創建2個實例
NSData *data = [[NSData alloc]initWithContentsOfFile:filepath]; NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
//把已歸檔的對象讀取。賦值給linepesist
linePesist *linepesist =[unarchiver decodeObjectForKey:CodeString]; [unarchiver finishDecoding];
//完成解檔
好了,屬性列表、歸檔解檔對象的存儲方法我們介紹到這里,讀者可以對比下有什么不同,呃…最明顯的應該是歸檔的代碼量多些,但是相應的,歸檔會具有非常好的伸縮性,至少從代碼上面看,是這樣的。