iOS資料持久化儲存-NSKeyedArchiver

weixin_33670713發表於2017-06-15
1076653-94e516c44fd878fd.png
歸檔檔案

歸檔(稱為序列化)是把物件轉為位元組碼,以檔案的形式儲存到磁碟上;程式執行過程中或者當再次重寫開啟程式的時候,可以通過解歸檔(反序列化)還原這些物件。歸檔解歸檔用於少量資料的持久化儲存和讀取。

歸檔和解歸檔常用API

//NSKeyedArchiver  API
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;

- (instancetype)initForWritingWithMutableData:(NSMutableData *)data;

- (void)finishEncoding;

- (void)encodeObject:(nullable id)objv forKey:(NSString *)key;
- (void)encodeBool:(BOOL)boolv forKey:(NSString *)key;
- (void)encodeInt:(int)intv forKey:(NSString *)key;
- (void)encodeFloat:(float)realv forKey:(NSString *)key;
- (void)encodeDouble:(double)realv forKey:(NSString *)key;
//NSKeyedUnarchiver   API
+ (nullable id)unarchiveObjectWithData:(NSData *)data;
+ (nullable id)unarchiveObjectWithFile:(NSString *)path;

- (instancetype)initForReadingWithData:(NSData *)data;

- (void)finishDecoding;

- (nullable id)decodeObjectForKey:(NSString *)key;
- (BOOL)decodeBoolForKey:(NSString *)key;
- (int)decodeIntForKey:(NSString *)key;
- (float)decodeFloatForKey:(NSString *)key;
- (double)decodeDoubleForKey:(NSString *)key;

歸檔的方式:

  • 針對物件進行歸檔(NSArray,NSDictionary等)
  • 對自定義的內容進行歸檔
  • 對自定義的物件進行歸檔
1、針對物件進行歸檔
- (void)objArchiver {
    
    //歸檔(序列化)
    NSArray *archiverAry = @[
                             @{@"Eugene" : @"ZhangYanJin"},
                             @{@"Chana" : @"LiChang"}
                             ];
    NSString *filePath = [self filePathWithName:@"Object"];
    if ([NSKeyedArchiver archiveRootObject:archiverAry toFile:filePath]) {
        NSLog(@"\n\n\n歸檔成功:路徑%@",filePath);
    }
    
    //解歸檔 (反序列化)
    NSArray *unArchiverAry = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"\n解歸檔成功 %@",unArchiverAry);
    
    /**
     總結:
     *優點:歸檔和解歸檔操作步驟簡單方便
     *缺點:一次只能歸檔一個物件,如果歸檔多個物件,需要分開麻煩,操作繁瑣費時
     */
}
- (void)customContentArchiver {
    
    //歸檔
    //1、使用Data存放歸檔資料
    NSMutableData *archiverData = [NSMutableData data];
    
    //2、根據Data例項建立和初始化歸檔物件
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiverData];
    
    //3、新增歸檔內容(設定鍵值對)
    [archiver encodeObject:@"Eugene" forKey:@"name"];
    [archiver encodeObject:@"man" forKey:@"sex"];
    [archiver encodeInt:25 forKey:@"age"];
    [archiver encodeObject:@[@"OC",@"Swift",@"Html"] forKey:@"laguage"];
    [archiver encodeObject:@{@"favorite" : @"cook"} forKey:@"life"];
    [archiver encodeCGPoint:CGPointMake(1.0, 2.0) forKey:@"point"];
    
    //4、完成歸檔
    [archiver finishEncoding];
    
    //5、將歸檔的資訊儲存到磁碟上
    NSString *filePath = [self filePathWithName:@"CustomContent"];
    if ([archiverData writeToFile:filePath atomically:YES]) {
        NSLog(@"\n\n\n歸檔成功:路徑%@",filePath);
    }
    
    //解歸檔
    //1、從磁碟讀取檔案,生成NSData例項
    NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath];

    //2、根據Data例項建立和初始化解歸檔物件
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData];

    //3、解歸檔,根據key值訪問
    NSString *name = [unarchiver decodeObjectForKey:@"name"];
    NSDictionary *life = [unarchiver decodeObjectForKey:@"life"];
    NSLog(@"\n解歸檔成功: %@ %@",name,life);
    
    //4、完成解歸檔
    [unarchiver finishDecoding];

    /**
     總結:
     *優點:可以同時歸檔多個物件、以及不同型別的物件(如:Int、CGFloat、CGPoint)
     *缺點:這裡的物件都是基本型別資料,如果我想對自己定義類生成的例項物件進行歸檔,這樣做將使操作又變得繁瑣費時了
     */
}
- (void)customObjectArchiver {
    
    //序列化和反序列化遵循NSCoding協議的自定義類
    
    //歸檔
    Person *person = [[Person alloc] init];
    person.name = @"Eugene";
    person.sex = @"man";
    person.age = 25;
    person.height = 175;
    
    NSString *filePath = [self filePathWithName:@"CustomObject"];

    if ([NSKeyedArchiver archiveRootObject:person toFile:filePath]) {
        NSLog(@"\n\n\n歸檔成功:路徑%@",filePath);
    }
    
    //解歸檔
    Person *unArchiverObj = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"\n解歸檔成功: %@ %@",unArchiverObj,unArchiverObj.name);
    
}
- (NSString *)filePathWithName:(NSString *)name {

    name = [[NSString alloc] initWithFormat:@"%@.archiver",name];
    
    //歸檔後的檔案是加密的,所以歸檔檔案的副檔名可以隨意取,我這裡字尾用archiver
    return [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:name];
}

注意:

  • 1、預設情況下,只能對NSDate, NSNumber, NSString, NSArray, or NSDictionary來進行歸檔。
  • 2、若對自定義的物件進行歸檔,需要實現NSCoding協議,並實現NSCoding方法。
  • NSCoding協議的方法:
  • - (void)encodeWithCoder:(NSCoder *)aCoder;
  • - (instancetype)initWithCoder:(NSCoder *)aDecoder;
  • 3、如果用了繼承,則子類一定要重寫NSCoding協議的兩個方法。

附:歸檔Demo

寫在最後

推薦:
一個簡單、執行緒安全的基於 key-value 的快取框架EGOCache

相關文章