iOS開發(fā)中數(shù)據(jù)持久化(三):NSKeyArchive歸檔解檔的實現(xiàn)

這篇文章主要寫NSKeyArchiver歸檔和NSKeyUnarchiver解檔的實現(xiàn)

最終存儲后的效果圖為:


image.png

Demo地址
對應(yīng)的文件是Human.m和ArchiveViewController.m

目的是希望能歸檔解檔自定義對象享扔,需要遵守NSSecureCoding協(xié)議予跌,這部分在上一篇iOS開發(fā)中數(shù)據(jù)持久化(二):NSUserDefault實現(xiàn)數(shù)據(jù)存儲

里面講過秩贰,所以human.m的實現(xiàn)和上一篇中person.m的實現(xiàn)類似说贝,這里直接寫代碼
在human.h中,聲明相應(yīng)的屬性

@interface Human : NSObject<NSSecureCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;


@end

在human.m文件中,實現(xiàn)相應(yīng)的協(xié)議方法

+ (BOOL)supportsSecureCoding {
    return YES;
}

//1.編碼方法
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
    [coder encodeObject:self.name forKey:@"HumanName"];
    [coder encodeInteger:self.age forKey:@"HumanAge"];
}

//2.解碼方法
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
    self = [super init];
    if (self) {
        self.name = [coder decodeObjectForKey:@"HumanName"];
        self.age = [coder decodeIntegerForKey:@"HumanAge"];
    }
    return self;
}

之后踏拜,創(chuàng)建ArchiveViewController鞋邑,繼承自UIViewController,主要有兩種歸檔腕窥、解檔方法(勉強可以算是兩種)粒没,我們希望將數(shù)據(jù)存儲到兩個不同的文件中

上面的效果圖中data1文件存儲的是第一種方法歸檔后的數(shù)據(jù)
data2文件存儲的是第二種方法歸檔后的數(shù)據(jù)
所以聲明兩個路徑以及歸檔按鈕、解檔按鈕

在ArchiveViewController.h中
聲明相應(yīng)的屬性

@property (nonatomic, strong) UIButton *archiveButton;
@property (nonatomic, strong) UIButton *unarchiveButton;
@property (nonatomic, copy) NSString *path1;
@property (nonatomic, copy) NSString *path2;

在.m文件中簇爆,懶加載以及完成基本的布局

//放置在Cache文件夾下
- (NSString *)path1 {
    if (_path1) {
        return _path1;
    }
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    _path1 = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Data1"];
    NSLog(@"path1 = %@",_path1);
    return _path1;
}

//放置在cache文件夾下
- (NSString *)path2 {
    if (_path2) {
        return _path2;
    }
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    _path2 = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Data2"];
    NSLog(@"path2 = %@",_path2);
    return _path2;
}

- (UIButton *)archiveButton {
    if (_archiveButton) {
        return _archiveButton;
    }
    _archiveButton = [[UIButton alloc] initWithFrame:CGRectZero];
    _archiveButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [_archiveButton setTitle:@"歸檔" forState:UIControlStateNormal];
    [_archiveButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [_archiveButton addTarget:self action:@selector(archiveData) forControlEvents:UIControlEventTouchUpInside];
    return _archiveButton;
}

- (UIButton *)unarchiveButton {
    if (_unarchiveButton) {
        return _unarchiveButton;
    }
    _unarchiveButton = [[UIButton alloc] initWithFrame:CGRectZero];
    _unarchiveButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [_unarchiveButton setTitle:@"解檔" forState:UIControlStateNormal];
    [_unarchiveButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [_unarchiveButton addTarget:self action:@selector(unarchiveData) forControlEvents:UIControlEventTouchUpInside];
    return _unarchiveButton;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.navigationController.navigationBar.translucent = NO;
    self.title = @"歸檔解檔實現(xiàn)";
    self.view.backgroundColor = [UIColor whiteColor];
    
    [self.view addSubview:self.archiveButton];
    [self.archiveButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view);
        make.centerY.equalTo(self.view);
        make.width.greaterThanOrEqualTo(@0);
        make.height.equalTo(@30);
    }];
    
    [self.view addSubview:self.unarchiveButton];
    [self.unarchiveButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view);
        make.top.equalTo(self.archiveButton.mas_bottom).offset(20);
        make.width.greaterThanOrEqualTo(@0);
        make.height.equalTo(@30);
    }];
}

下面就是歸檔入蛆、解檔的具體實現(xiàn),在archiveData()方法中實現(xiàn)歸檔哨毁,在unarchiveData()方法中實現(xiàn)解檔

這部分也是花費時間最多的部分枫甲,因為我設(shè)備是ios14,看原先的博客都是使用archiveRootObject...tofile就可將對象歸檔到文件中
但是在iOS14中想幻,這個方法已經(jīng)被棄用了

后面只能看蘋果開發(fā)文檔
發(fā)現(xiàn)可以算做兩種方法實現(xiàn)歸檔、解檔
(本質(zhì)都是一樣的脏毯,獲取到歸檔后的NSData數(shù)據(jù)闹究,然后將其寫入相應(yīng)的文件中)
一種是使用類方法實現(xiàn)
一種是使用實例方法實現(xiàn),可以添加對應(yīng)的鍵值

類方法實現(xiàn)歸檔解檔

這個歸檔的路徑使用path1
歸檔相關(guān)的代碼為:

- (void)archiveData {
   Human *human = [[Human alloc] init];
    human.name = @"落葉兮兮";
    human.age = 24;

    //第一種方法食店,使用NSKeyArchiver類方法渣淤,將對象轉(zhuǎn)化為NSData价认,然后寫入指定的文件中
    NSError *error = nil;
    NSData *data1 = [NSKeyedArchiver archivedDataWithRootObject:human requiringSecureCoding:YES error:&error];
    if (error) {
        NSLog(@"歸檔失敗自娩,失敗的原因是%@",error);
    }

    BOOL success = [data1 writeToFile:self.path1 atomically:YES];
    if (success) {
        NSLog(@"寫入成功");
    } else {
        NSLog(@"寫入失敗");
    }
}

運行后,點擊歸檔椒功,就可以看到相應(yīng)的文件存在


image.png

對應(yīng)的解檔讀取數(shù)據(jù)的代碼如下:

- (void)unarchiveData {
     NSLog(@"開始解檔數(shù)據(jù)");
    //使用NSKeyedUnarchiver類方法解析
    NSData *data1 = [NSData dataWithContentsOfFile:self.path1];
    NSError *error1 = nil;
    Human *human1 = [NSKeyedUnarchiver unarchivedObjectOfClass:[Human class] fromData:data1 error:&error1];
    if (error1) {
        NSLog(@"解檔數(shù)據(jù)失敗,失敗的原因是%@",error1);
    } else {
        NSLog(@"解檔數(shù)據(jù)成功");
        NSLog(@"human name = %@,age = %ld",human1.name,human1.age);
    }
}

運行成功动漾,點擊解檔,可以讀取相應(yīng)的內(nèi)容

使用實例方法歸檔和解檔

這個歸檔的路徑使用path2
歸檔的代碼為:

- (void)archiveData {
     NSLog(@"開始歸檔數(shù)據(jù)");
    Human *human = [[Human alloc] init];
    human.name = @"落葉兮兮";
    human.age = 24;
//第二種使用NSKeyArchiver的實例方法,編碼時使用相應(yīng)的鍵值旱眯,然后將編碼后的數(shù)據(jù)寫入執(zhí)行的路徑中
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
    [archiver encodeObject:human forKey:@"Human"];
    [archiver finishEncoding];
    NSLog(@"NSKeyArchiver編碼的數(shù)據(jù)為%@",archiver.encodedData);
    [archiver.encodedData writeToFile:self.path2 atomically:YES];
    NSLog(@"歸檔結(jié)束");
}

解檔的代碼為:(注意解檔時的鍵值要和歸檔的鍵值保持一致)

 //使用NSKeyedUnarchiver實例方法解析
    NSError *error2 = nil;
    NSData *data2 = [NSData dataWithContentsOfFile:self.path2];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data2 error:&error2];
    Human *human2 = [unarchiver decodeObjectOfClass:[Human class] forKey:@"Human"];
    [unarchiver finishDecoding];
    if (error2) {
        NSLog(@"解檔數(shù)據(jù)失敗,失敗的原因是%@",error2);
    } else {
        NSLog(@"解檔數(shù)據(jù)成功");
        NSLog(@"human name = %@,age = %ld",human2.name,human2.age);
    }

運行后删豺,可以查看到相應(yīng)的文件


image.png

而且,來年各種功能方法存儲的是一樣的內(nèi)容妈拌,data1文件的大小是243kb蓬蝶,data2文件的大小是244kb,或許就是因為data2存儲時設(shè)置了鍵值“Human”

總結(jié)

最終存儲后的效果圖為:


image.png

Demo地址
對應(yīng)的文件是Human.m和ArchiveViewController.m

iOS開發(fā)中數(shù)據(jù)持久化總結(jié)(一);
iOS開發(fā)中數(shù)據(jù)持久化總結(jié)(二):NSUserDefault實現(xiàn)數(shù)據(jù)存儲
ios開發(fā)中數(shù)據(jù)持久化總結(jié)(三):NSKeyArchive歸檔解檔的實現(xiàn)
ios開發(fā)中數(shù)據(jù)持久化總結(jié)(四):使用FMDataBase存儲數(shù)據(jù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缓窜,隨后出現(xiàn)的幾起案子定续,更是在濱河造成了極大的恐慌私股,老刑警劉巖摹察,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件港粱,死亡現(xiàn)場離奇詭異旦签,居然都是意外死亡寸宏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門羔巢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來罩阵,“玉大人,你說我怎么就攤上這事啊片。” “怎么了匪燕?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵帽驯,是天一觀的道長书闸。 經(jīng)常有香客問我,道長浆劲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任蛉威,我火速辦了婚禮走哺,結(jié)果婚禮上哲虾,老公的妹妹穿的比我還像新娘择示。我一直安慰自己,他們只是感情好汪诉,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布谈秫。 她就那樣靜靜地躺著,像睡著了一般拟烫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上课竣,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天置媳,我揣著相機與錄音,去河邊找鬼迂曲。 笑死寥袭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纠永。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼涉波,長吁一口氣:“原來是場噩夢啊……” “哼炭序!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窗声,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辜纲,失蹤者是張志新(化名)和其女友劉穎拦耐,沒想到半個月后见剩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡固翰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年羹呵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片方援。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡涛癌,死狀恐怖送火,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情弃衍,我是刑警寧澤坚俗,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站速缆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏艺糜。R本人自食惡果不足惜幢尚,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望真慢。 院中可真熱鬧理茎,春花似錦管嬉、人聲如沸园爷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呀癣,卻和暖如春弦赖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蹬竖。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工币厕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留列另,地道東北人旦装。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓阴绢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親呻袭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容