oc歸檔與解檔(序列化和反序列化)

Foundation框架的歸檔功能

將對(duì)象存儲(chǔ)轉(zhuǎn)換為二進(jìn)制序列的過(guò)程成為歸檔、打包或編碼,逆變換稱為解檔、解碼或?qū)ο筮€原。

可以使用NSKeyedArchiver和NSKeyedUnarchiver完成對(duì)象的歸檔和解檔操作,而他們都是抽象類NSCoder的子類。

所有可以歸檔的對(duì)象都必須要適用于協(xié)議NSCoding。協(xié)議NSCoding在Foundation/NSObject.h中定義,NSObject自身并不采用該協(xié)議。NSString、NSDictionary等Foundation框架的主要類都適用協(xié)議NSCoding。

協(xié)議NSCoding按照如下方式聲明:

@protocolNSCoding

-(void)encodeWithCoder:(NSCoder*)coder

-(id)initWithCoder:(NSCoder*)coder

歸檔方法的定義

協(xié)議NSCoding中,函數(shù)encodeWithCoder:定義了歸檔自身的方法。

- (void)encodeWithCoder:(NSCoder *)coder

{

????[super encodeWithCoder:coder];

????//超類需要適用NSCoding協(xié)議

????[coder encodeObject:對(duì)象 forKey:關(guān)鍵詞字符串];

????[coder encodeInt:實(shí)數(shù)變量 forKey:關(guān)鍵詞字符串];

}

如果超類不適用協(xié)議NSCoding,則不能調(diào)用encodeWithCoder:方法。

類自身對(duì)包含的實(shí)例變量歸檔。在類沒(méi)有自己的實(shí)例變量且超類中定義了方法encodeWithCoder:的情況下,該方法就不需要在定義了。

通過(guò)使用NSString字符串作為鍵值,可以指定歸檔解檔的內(nèi)容。讓某個(gè)類實(shí)例歸檔時(shí),它的實(shí)例變量必須指定成不同的鍵值。在單個(gè)對(duì)象內(nèi)部,如果超類使用了一個(gè)鍵值,那么子類中就不能使用該鍵值。鍵值只需在同一個(gè)類內(nèi)區(qū)分出來(lái)即可,不同的類可使用相同的鍵值。

當(dāng)對(duì)象圖有閉環(huán)時(shí),同一個(gè)對(duì)象會(huì)重復(fù)要求歸檔,實(shí)際上已歸檔的對(duì)象是不用重復(fù)歸檔的。

解檔方法的定義

- (instancetype)initWithCoder:(NSCoder *)coder{

????self= [superinitWithCoder:coder];

????//超類不適應(yīng)于協(xié)議NSCoding時(shí),????

????//建議使用 self = [super init];

if (self) {

????self.name= [coder decodeObjectForKey: 鍵值];

????self.age= [coder decodeIntForKey: 鍵值];? ?

?????}

????returnself;

}

歸檔示例程序:

main.m

#import? <Foundation/Foundation.h>

#import"Person.h"

int main(intargc,constchar* argv[])?{? ??

????@autoreleasepool {? ? ? ??

????????Person * p = [[Person alloc] init];? ? ? ?

?????????p.name= @"lu";? ? ? ?

?????????p.age=18;? ? ? ?

?????????p.weight=100.0;

????????BOOLisSuccess = [NSKeyedArchiver archiveRootObject:p toFile:@"/Users/lu/Desktop/test.plist"];if(isSuccess) {NSLog(@"歸檔成功");? ? ?

?????????? }else{

????????????????NSLog(@"歸檔失敗");? ? ??

? ????????}??

????? }

????return0;

}


解檔示例程序:

main.m

intmain(intargc,constchar* argv[]) {? ??

????@autoreleasepool {

????????????//解檔????

????????????Person * p = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/lu/Desktop/test.plist"];

????????????NSLog(@"%@",p.name);

????????????NSLog(@"%d",p.age);

????????????NSLog(@"%f",p.weight);? ??

????????}

????????return0;

}

若類中實(shí)例變量為其他類對(duì)象,則還需要在其他類中實(shí)現(xiàn)encodeWithCoder:和initWithCoder:方法。

示例程序:

Dog.m

#import"Dog.h"?

@implementation Dog

- (void)encodeWithCoder:(NSCoder *)coder{?

? ? ?[coder encodeObject:self.nameforKey:@"name"];? ?

?????[coder encodeInt:self.ageforKey:@"age"];}

- (instancetype)initWithCoder:(NSCoder *)coder{

????self= [superinit];

????if (self) {

????????self.name= [coder decodeObjectForKey:@"name"];self.age= [coder decodeIntForKey:@"age"];? ? }

????????return self;

}

@end


student.m

#import"Student.h"

#import"Dog.h"

@implementationStudent

//歸檔

- (void)encodeWithCoder:(NSCoder *)coder{??

?[coder encodeObject:self.nameforKey:@"name"];? ?

?[coder encodeInt:self.scoreforKey:@"score"];??

?[coder encodeInt:self.numberforKey:@"number"];?

? [coder encodeObject:self.dogforKey:@"dog"];}

//解檔

- (instancetype)initWithCoder:(NSCoder *)coder{

self = [superinit];

????if (self) {

????self.name= [coder decodeObjectForKey:@"name"];

????self.score= [coder decodeIntForKey:@"score"];

????self.number= [coder decodeIntForKey:@"number"];

????self.dog= [coder decodeObjectForKey:@"dog"];??

? }

????return self;

}

@end

main.m

int main(intargc,constchar* argv[]) {?

?? @autoreleasepool {? ? ??

? ? ?Student * stu = [[Student alloc] init];? ? ? ??

????stu.name= @"di";? ? ? ?

?????stu.score=70;? ? ? ?

?????stu.number=20;? ? ??

? ????Dog * d = [[Dog alloc] init];? ? ? ?

?????d.name= @"Chen";? ? ?

? ? ? d.age=10;? ? ??

? ????stu.dog= d;

//歸檔

BOOL isSuccess = [NSKeyedArchiver archiveRootObject:stu toFile:@"/Users/lu/Desktop/Stu.txt"];if(isSuccess) {NSLog(@"Yes");? ? ?

?? }else{

????????NSLog(@"NO");? ??

? ? }

//解檔

????Student * stu3 = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/lu/Desktop/Stu.txt"];NSLog(@"%@", stu3.name);

????NSLog(@"%d", stu3.score);

????NSLog(@"%d", stu3.number);

????NSLog(@"%@", stu3.dog.name);

????NSLog(@"%d", stu3.dog.age);??

????? }

????return0;?

?}

對(duì)多個(gè)對(duì)象進(jìn)行歸檔,可以先將多個(gè)對(duì)象存儲(chǔ)于NSArray、NSMutableArray、NSDictionary或NSMutableDictionary中,再進(jìn)行歸檔。

示例程序:

NSArray* stuArray = @[stu, stu1, stu2];

BOOLisSuccess = [NSKeyedArchiver archiveRootObject:stuArray toFile:@"/Users/lu/Desktop/stuArray.txt"];

if(isSuccess) {

????NSLog(@"Yes");? ? ? ??

}else{

????NSLog(@"NO");? ? ? ??

}

最后一種方式利用NSData對(duì)多個(gè)對(duì)象進(jìn)行歸檔解檔

示例程序

main.m

#import

#import"Person.h"

int main(intargc,constchar* argv[]) {??

? @autoreleasepool {? ? ? ?

?????Person * p = [[Person alloc] init];? ??

? ? ?p.name= @"dou";??

? ? ?p.age=22;? ??

? ? ?p.weight=120.00;? ?

?? ? Person * p2 = [[Person alloc] init];?

? ? ? p2.name= @"dashu";??

? ? ? p2.age=24;??

? ? ? p2.weight=140.3;??

? ? ? NSMutableData * data = [NSMutableData data];//? ? ? ? 根據(jù)二進(jìn)制流創(chuàng)建NSkeyedArchiver對(duì)象????

? ? ? NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

//? ? ? ? 對(duì)對(duì)象進(jìn)行歸檔操作

????[archiver encodeObject:p forKey:@"person1"];? ??

? ? ?[archiver encodeObject:p2 forKey:@"person2"];

//? ? ? ? 結(jié)束歸檔

/*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

歸檔如果沒(méi)有結(jié)束 finishEncoding就不會(huì)歸檔成功,產(chǎn)生文件無(wú)法打開? ? The data couldn't be read because it isn't in the correct format.

*/

[archiver finishEncoding];

BOOL isSuccess = [data writeToFile:@"/Users/lu/Desktop/Data.plist"atomically:YES];if(isSuccess) {

? ? ? ?NSLog(@"歸檔成功!");? ?

?? ? }else{

????????NSLog(@"歸檔失敗");? ? ??

? }

//解檔NSData * data = [NSData dataWithContentsOfFile:@"/Users/lu/Desktop/Data.plist"];? ? ? ? NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];? ? ??

? Person * p = [unarchiver decodeObjectForKey:@"person1"];? ? ?

? Person * p2 = [unarchiver decodeObjectForKey:@"person2"];

//結(jié)束解檔 解檔沒(méi)有finishDecoding無(wú)影響

// [unarchiver finishDecoding];

NSLog(@"%@", p.name);

NSLog(@"%d", p.age);NSLog(@"%f", p.weight);

NSLog(@"%@", p2.name);NSLog(@"%d", p2.age);NSLog(@"%f", p2.weight);? ?

?}

return0;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容