NSCoding
1、為了將應(yīng)用數(shù)據(jù)存儲(chǔ)到硬盤中,iOS提供基本的文件API姓迅、Property List序列化、SQLite俊马、CoreData以及NSCoding丁存。對于輕量級(jí)的數(shù)據(jù)要求,NSCoding因其簡單而成為一種比較合適的方式柴我。 NSCoding是一個(gè)你需要在數(shù)據(jù)類上要實(shí)現(xiàn)的協(xié)議以支持?jǐn)?shù)據(jù)類和數(shù)據(jù)流間的編碼和解碼解寝。數(shù)據(jù)流可以持久化到硬盤。
2艘儒、是類對象本身數(shù)據(jù)的寫入到本地文件聋伦。
我 們需要實(shí)現(xiàn)兩個(gè)方法: encodeWithCoder和initWithEncoder。encodeWithCoder就是編碼界睁,initWithCoder就是解碼觉增。 encodeWithCoder方法傳入的是一個(gè)NSCoder對象,實(shí)現(xiàn)的時(shí)候我們就可以調(diào)用encodeObject翻斟、encodeFloat逾礁、 encodeInt等各種方法并通過指定鍵值進(jìn)行編碼。
對模型對象進(jìn)行歸檔
在Cocoa世界中访惜,歸檔(archiving)是指另一種形式的序列化嘹履,但它是任何對象都可以實(shí)現(xiàn)的更常規(guī)的類型腻扇。專門編寫用于保存數(shù)據(jù)的任何模型對象都應(yīng)該支持歸檔。使用對模型對象進(jìn)行歸檔的技術(shù)可以輕松將復(fù)雜的對象寫入文件植捎,然后再從中讀取它們衙解。
只要在類中實(shí)現(xiàn)的每個(gè)屬性都是標(biāo)量(int.float)或是遵循NSCoding協(xié)議的某個(gè)類的實(shí)例阳柔,你就可以對整個(gè)對象進(jìn)行完全的歸檔焰枢。由于大多數(shù)支持存儲(chǔ)數(shù)據(jù)的Foundation和Cocoa Touch類都遵循NSCoding協(xié)議(除UIImage)。
還有一個(gè)協(xié)議應(yīng)該和NSCoding協(xié)議一起實(shí)現(xiàn)舌剂,那就是NSCopying協(xié)議济锄。后者允許復(fù)制對象,這使你在使用數(shù)據(jù)模型對象時(shí)具備了較大的靈活性霍转。
遵循NSCoding協(xié)議
NSCoding協(xié)議聲明了兩個(gè)方法荐绝,這兩個(gè)方法都是必需的。一個(gè)方法將對象編碼到歸檔中避消,另一個(gè)方法對歸檔解碼來創(chuàng)建一個(gè)新對象低滩。
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (instancetype)initWithCoder:(NSCoder *)aDecoder;
這兩個(gè)方法都傳遞一個(gè)NSCoder實(shí)例,使用方法和NSUserDefaults相似岩喷。也可以使用KVC對對象和原生數(shù)據(jù)類型(int,float)進(jìn)行編碼和解碼
遵循NSCoding協(xié)議
NSCoding協(xié)議聲明了兩個(gè)方法恕沫,這兩個(gè)方法都是必需的。一個(gè)方法將對象編碼到歸檔中纱意,另一個(gè)方法對歸檔解碼來創(chuàng)建一個(gè)新對象婶溯。這兩個(gè)方法都傳遞一個(gè)NSCoder實(shí)例,使用方法和NSUserDefaults相似偷霉。也可以使用KVC對對象和原生數(shù)據(jù)類型(int,float)進(jìn)行編碼和解碼迄委。
對某個(gè)對象進(jìn)行編碼的方法可能看起來如下:
(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:foo forKey:kFooKey];
[aCoder encodeObject:bar forKey:kBarKey];
[aCoder encodeInt:someInt forKey:kSomeIntKey];
[aCoder encodeFloat:someFloat forKey:kSomeFloat];
}
若要我們在項(xiàng)目中支持歸檔,必須使用正確的編碼方法將所有實(shí)例變量編碼成encoder类少。
如果要子類化某個(gè)也遵循NSCoding的類叙身,還需要確保對超類調(diào)用 encodeWithCoder: 方法,你的方法將如下所示:(void)encodeWithCoder:(NSCoder *)aCoder{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:foo forKey:kFooKey];
[aCoder encodeObject:bar forKey:kBarKey];
[aCoder encodeInt:someInt forKey:kSomeIntKey];
[aCoder encodeFloat:someFloat forKey:kSomeFloat];
}
我們還需要實(shí)現(xiàn)一個(gè)通過NSCoder解碼的對象初始化方法硫狞,恢復(fù)我們之前歸檔的對象曲梗。實(shí)現(xiàn)initWithCoder:方法比實(shí)現(xiàn)encodeWithCoder:方法稍微復(fù)雜一些。
如果直接對NSObject進(jìn)行子類化妓忍,或者對某些不遵循NSCoding的其他類進(jìn)行子類化虏两,則你的方法看起來如下
(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
foo = [aDecoder decodeObjectForKey:kFooKey];
bar = [aDecoder decodeObjectForKey:kBarKey];
someInt = [aDecoder decodeObjectForKey:kSomeIntKey];
someFloat = [aDecoder decodeObjectForKey:kAgeKey];
}
return self;
}
該方法使用
[super init] 初始化對象實(shí)例,如果初始化成功世剖,則它通過解碼NSCoder的實(shí)例中傳遞的值來設(shè)置其屬性定罢。
當(dāng)為某個(gè)具有父類且遵循NSCoding的類實(shí)現(xiàn)NSCoding時(shí),
initWithCoder:方法應(yīng)稍有不同旁瘫。
它不再對super調(diào)用init祖凫,
而是調(diào)用initWithCoder,像這樣:(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]) {
foo = [aDecoder decodeObjectForKey:kFooKey];
bar = [aDecoder decodeObjectForKey:kBarKey];
someInt = [aDecoder decodeObjectForKey:kSomeIntKey];
someFloat = [aDecoder decodeObjectForKey:kAgeKey];
}
return self;
}
只要實(shí)現(xiàn)這兩個(gè)方法琼蚯,就可以對所有對象的屬性進(jìn)行編碼和解碼,然后便可以對對象進(jìn)行歸檔惠况,并且可以將其寫入歸檔或者從歸檔中讀取它們遭庶。