1、對象歸檔
所謂對象歸檔,類似于“序列化”機(jī)制,歸檔就是用某種格式把一個或多 個對象保存到指定文件中,方便以后從文件中恢復(fù)他們。
1.1 使用NSKeyedArchiver歸檔
NSKeyedArchiver和NSKeyedUnarchiver
對系統(tǒng)類型直接歸檔
archiveRootObject: toFile:
unarchiveObjectWithFile:
//對象歸檔
- (void)test5{
//第一種方法,直接調(diào)用NSKeyedArchiver
//先創(chuàng)建一個NSDictionary對象
NSDictionary *dict = @{
@"Objective-C" : @89,
@"Rubby" : @69,
@"Python" : @75,
@"Perl" : @109
};
// 對dict對象進(jìn)行歸檔
NSString *filePath = @"/Users/lwg/Desktop/SettingBundle/SettingBundle/dict.archive";
[NSKeyedArchiver archiveRootObject:dict toFile:filePath];
// 讀取dict.archive
NSDictionary *dict1 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",dict1);
}
1.2 實現(xiàn)NSCoding協(xié)議
一般來說,如果對象的實例變量是OC基本類型,并且實現(xiàn)了NSCoding協(xié)議,則可直接調(diào)用encodingObject:forKey:方法來歸檔該實例變量,使用decodeObjectForKey:方法恢復(fù)該實例變量即可。
如果需要歸檔、恢復(fù)任意自定義類的實例,那么該類型應(yīng)該實現(xiàn)NSCoding協(xié)議如下兩個方法:
initWithCoder:
encodeWithCoder:
@interface FKApple : NSObject<NSCoding>
@property (nonatomic,copy) NSString *color;
@property (nonatomic,assign) double weight;
@property (nonatomic,assign) int size;
- (id)initWithColor:(NSString *)color weight:(double)weight size:(int)size;
@end
方法實現(xiàn)
- (void)encodeWithCoder:(NSCoder *)aCoder{
//調(diào)用NSCoder的方法歸檔該對象的每個實例變量
[aCoder encodeObject:_color forKey:@"color"];
[aCoder encodeDouble:_weight forKey:@"weight"];
[aCoder encodeInt:_size forKey:@"size"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
// 使用NSCoder恢復(fù)color、weight、size這3個key
// 所對應(yīng)的value,并將恢復(fù)的value賦給當(dāng)前對象的3個實例變量
_color = [aDecoder decodeObjectForKey:@"color"];
_weight = [aDecoder decodeDoubleForKey:@"weight"];
_size = [aDecoder decodeIntForKey:@"size"];
return self;
}
1.3使用NSData完成自定義歸檔
上面的方法每次只能將單個對象作為root進(jìn)行歸檔或者恢復(fù),如果希望一次性收集多個對象,并進(jìn)行歸檔到單個文件中,可以使用NSMutableData來創(chuàng)建NSKeyedArchiver和NSKeyedUnarchiver對象。
步驟如下:
1.以NSMutableData作為參數(shù),創(chuàng)建NSKeyedArchiver對象;
2.重復(fù)調(diào)用NSKeyedArchiver對象的encodeObject:forKey:方法來歸檔所有需要歸檔到一個文件中的對象。
3.調(diào)用NSKeyedArchiver對象的finishEncoding方法結(jié)束歸檔;
4.根據(jù)需要,程序可以選擇將保存歸檔數(shù)據(jù)的NSData通過網(wǎng)絡(luò)傳輸或者輸出到磁盤文件上。
// 使用NSData完成自定義歸檔
// 一次性將多個對象歸檔到單個文件中
- (void)test6{
//先創(chuàng)建一個NSDictionary對象
NSDictionary *dict = @{
@"Objective-C" : @89,
@"Rubby" : @69,
@"Python" : @75,
@"Perl" : @109
};
// 創(chuàng)建一個NSSet對象
NSSet *set = [NSSet setWithObjects:@"ios",@"Java",@"OC", nil];
FKApple *apple = [[FKApple alloc] initWithColor:@"紅色" weight:3.4 size:20];
// 創(chuàng)建一個NSMutableData對象,用于保存歸檔數(shù)據(jù)
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// 重復(fù)調(diào)用此方法
[arch encodeObject:dict forKey:@"dict"];
[arch encodeObject:set forKey:@"set"];
[arch encodeObject:apple forKey:@"apple"];
[arch finishEncoding];
// 程序?qū)SData緩存區(qū)保存的數(shù)據(jù)寫入文件
NSString *filePath = @"/Users/lwg/Desktop/SettingBundle/SettingBundle/multi.archive";
if ([data writeToFile:filePath atomically:YES] == NO) {
NSLog(@"歸檔失??!");
}
// 讀取歸檔
NSData *data1 = [NSData dataWithContentsOfFile:filePath];
NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data1];
NSDictionary *dict1 = [unarch decodeObjectForKey:@"dict"];
NSSet *set1 = [unarch decodeObjectForKey:@"set"];
FKApple *apple1 = [unarch decodeObjectForKey:@"apple"];
[unarch finishDecoding];
NSLog(@"%@",dict1);
NSLog(@"%@",set1);
NSLog(@"%@",apple1);
}
1.4使用歸檔實現(xiàn)深復(fù)制
當(dāng)程序歸檔一個對象時,系統(tǒng)會把該對象關(guān)聯(lián)的所有數(shù)據(jù)都轉(zhuǎn)化為字節(jié)數(shù)據(jù);如果程序從這些字節(jié)數(shù)據(jù)中恢復(fù)該對象,恢復(fù)出來的對象與原對象完全相同,但沒有任何公用的部分,這就實現(xiàn)了深復(fù)制。
// 利用歸檔實現(xiàn)深復(fù)制
- (void)deepCopy{
NSDictionary *dict = @{
@"one" : [[FKApple alloc] initWithColor:@"紅色" weight:3.4 size:20],
@"two" : [[FKApple alloc] initWithColor:@"綠色" weight:2.8 size:14]
};
// 將歸檔對象的數(shù)據(jù)寫入NSData
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict];
// 從NSData對象中恢復(fù)對象,這樣既可完成深復(fù)制
NSDictionary *dictCopy = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// 獲取復(fù)制后的對象
FKApple *app = [dictCopy objectForKey:@"one"];
// 修改對象屬性
[app setColor:@"紫色"];
// 獲取原始對象
FKApple *oneApp = [dict objectForKey:@"one"];
// 訪問該對象顏色,發(fā)現(xiàn)并沒有改變
NSLog(@"dict中key為one對應(yīng)的顏色為:%@,復(fù)制后的app顏色為:%@",oneApp.color,app.color);
}