首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 自定義物件歸檔解檔:NSCoding 協議完整實現

     編輯:關於C語言

NSCoding 協議

自定義物件若要支援歸檔 (序列化) 必須實現 `NSCoding` 兩個必要方法:

  • - (void)encodeWithCoder:(NSCoder*)coder:編碼實例變數
  • - (id)initWithCoder:(NSCoder*)coder:解碼並初始化

Person 類別完整實現


// Person.h
#import 

@interface Person : NSObject 
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *email;
@property (nonatomic, copy) NSString *password;
@property (nonatomic, assign) NSInteger age;
@end

// Person.m
#import "Person.h"

static NSString *const kAge = @"age";
static NSString *const kName = @"name";
static NSString *const kEmail = @"email";
static NSString *const kPassword = @"password";

@implementation Person

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeInteger:self.age forKey:kAge];
    [coder encodeObject:self.name forKey:kName];
    [coder encodeObject:self.email forKey:kEmail];
    [coder encodeObject:self.password forKey:kPassword];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _age = [coder decodeIntegerForKey:kAge];
        _name = [[coder decodeObjectForKey:kName] copy];
        _email = [[coder decodeObjectForKey:kEmail] copy];
        _password = [[coder decodeObjectForKey:kPassword] copy];
    }
    return self;
}

- (void)dealloc {
    [_name release];
    [_email release];
    [_password release];
    [super dealloc];
}

@end

歸檔與解檔操作


#import 
#import "Person.h"

int main() {
    @autoreleasepool {
        // 建立物件
        Person *person = [[Person alloc] init];
        person.name = @"jack";
        person.age = 20;
        person.email = @"jack@163.com";
        person.password = @"12345";

        // 歸檔路徑
        NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/person.archive"];

        // 歸檔
        BOOL success = [NSKeyedArchiver archiveRootObject:person toFile:path];
        if (success) NSLog(@"歸檔成功");

        // 解檔
        Person *restored = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
        NSLog(@"name=%@, age=%ld, email=%@, password=%@",
              restored.name, restored.age, restored.email, restored.password);
    }
    return 0;
}

關鍵點補充

主題說明
編碼基本型別`encodeInteger:forKey:` `encodeFloat:forKey:` `encodeBool:forKey:` 等
編碼物件`encodeObject:forKey:` (需物件也實現 NSCoding)
解碼基本型別`decodeIntegerForKey:` `decodeFloatForKey:` `decodeBoolForKey:`
解碼物件`decodeObjectForKey:` 回傳 `id`,需轉型並 `copy` (若屬性為 copy)
版本演進新增欄位時解碼端用 `decodeObjectForKey:` 可能回傳 `nil`,需提供預設值
安全性`NSKeyedArchiver` 預設不加密,敏感資料 (密碼) 應先加密再歸檔
替代方案JSON (Codable)、Protocol Buffers、Property List (plist) 適用跨平台/人類可讀場景

NSSecureCoding (iOS 6+ / OS X 10.8+)


@interface Person : NSObject 
+ (BOOL)supportsSecureCoding { return YES; }
// initWithCoder 中驗證類別
- (id)initWithCoder:(NSCoder*)coder {
    self = [super init];
    if (self) {
        // 只解碼預期類別,防止物件注入攻擊
        _name = [coder decodeObjectOfClass:[NSString class] forKey:kName];
        ...
    }
    return self;
}

`NSSecureCoding` 強制解碼時指定類別,提升安全性,App Store 上架建議採用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved