前面兩種方式(plist文件讀寫、NSUserDefaults偏好設置)只能保存 plist 支持的基本數據類型,那么要保存自定義的類對象,蘋果提供了NSKeydeArchiver歸檔。
歸檔在iOS中是另一種形式的序列化,只要遵循了 NSCoding
協議的對象都可以通過它實現序列化。由于絕大多數支持存儲數據的類都遵循了 NSCoding
協議,因此,對于大多數類來說,歸檔相對而言還是比較容易實現的。
如果對象是 NSString、NSDictionary、NSArray、NSData、NSNumber
等類型,可以直接用 NSKeyedArchiver
歸檔和 NSKeyedUnarchiver
解檔。
1、遵循NSCoding協議
NSCoding
協議聲明了兩個方法,這兩個方法都是必須實現的:
encodeWithCoder
:用來說明如何將對象編碼到歸檔中。
每次歸檔對象時,都會調用這個方法。一般在這個方法里面指定如何歸檔對象中的每個實例變量,可以使用encodeObject:forKey:
方法歸檔實例變量。initWithCoder
:用來說明如何進行解檔來獲取一個新對象。
每次從文件中恢復(解碼)對象時,都會調用這個方法。一般在這個方法里面指定如何解碼文件中的數據為對象的實例變量,可以使用decodeObject:forKey
方法解碼實例變量。
// 1.遵循NSCoding協議
@interface Person : NSObject <NSCoding>
// 2.設置屬性
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger age;
@end
@implementation Person
// 解檔
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
// 歸檔
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
@end
2、NSKeyedArchiver歸檔
調用 NSKeyedArchiver
的 archiveRootObject:toFile:
方法把對象歸檔。
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).lastObject;
NSString *file = [path stringByAppendingPathComponent:@"person.data"];
Person *person = [[Person alloc] init];
person.name = @"Jay";
person.age = 18;
[NSKeyedArchiver archiveRootObject:person toFile:file];
3、NSKeyedUnarchiver解檔
調用 NSKeyedUnarchiver
的 unarchiveObjectWithFile:
方法從文件中解檔對象。
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).lastObject;
NSString *file = [path stringByAppendingPathComponent:@"person.data"];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
if (person) {
self.nameLable.text = person.name;
self.ageLable.text = [NSString stringWithFormat:@"%ld", person.age];
}
- 必須遵循并實現
NSCoding
協議 - 保存文件的擴展名可以任意指定
- 繼承時必須先調用父類的歸檔解檔方法,這里因為父類是
NSObject
,就不用了。如果父類也遵守了NSCoding
協議,請注意:- 應該在encodeWithCoder:方法中加上一句
[super encodeWithCode:encode]
,確保繼承的實例變量也能被編碼,即也能被歸檔。 - 應該在initWithCoder:方法中加上一句
self = [super initWithCoder:decoder]
,確保繼承的實例變量也能被解碼,即也能被恢復。
- 應該在encodeWithCoder:方法中加上一句
通過文件讀寫(plist)保存的數據是直接顯示出來的,不安全。而通過 NSKeydeArchiver
歸檔方法保存的數據在文件中打開是編碼,更安全。