iOS开发中数据持久化(三):NSKeyArchive归档解档的实现

这篇文章主要写NSKeyArchiver归档和NSKeyUnarchiver解档的实现

最终存储后的效果图为:


image.png

Demo地址
对应的文件是Human.m和ArchiveViewController.m

目的是希望能归档解档自定义对象,需要遵守NSSecureCoding协议,这部分在上一篇iOS开发中数据持久化(二):NSUserDefault实现数据存储

里面讲过,所以human.m的实现和上一篇中person.m的实现类似,这里直接写代码
在human.h中,声明相应的属性

@interface Human : NSObject<NSSecureCoding>

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


@end

在human.m文件中,实现相应的协议方法

+ (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;
}

之后,创建ArchiveViewController,继承自UIViewController,主要有两种归档、解档方法(勉强可以算是两种),我们希望将数据存储到两个不同的文件中

上面的效果图中data1文件存储的是第一种方法归档后的数据
data2文件存储的是第二种方法归档后的数据
所以声明两个路径以及归档按钮、解档按钮

在ArchiveViewController.h中
声明相应的属性

@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 = @"归档解档实现";
    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);
    }];
}

下面就是归档、解档的具体实现,在archiveData()方法中实现归档,在unarchiveData()方法中实现解档

这部分也是花费时间最多的部分,因为我设备是ios14,看原先的博客都是使用archiveRootObject...tofile就可将对象归档到文件中
但是在iOS14中,这个方法已经被弃用了

后面只能看苹果开发文档
发现可以算做两种方法实现归档、解档
(本质都是一样的,获取到归档后的NSData数据,然后将其写入相应的文件中)
一种是使用类方法实现
一种是使用实例方法实现,可以添加对应的键值

类方法实现归档解档

这个归档的路径使用path1
归档相关的代码为:

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

    //第一种方法,使用NSKeyArchiver类方法,将对象转化为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(@"写入失败");
    }
}

运行后,点击归档,就可以看到相应的文件存在


image.png

对应的解档读取数据的代码如下:

- (void)unarchiveData {
     NSLog(@"开始解档数据");
    //使用NSKeyedUnarchiver类方法解析
    NSData *data1 = [NSData dataWithContentsOfFile:self.path1];
    NSError *error1 = nil;
    Human *human1 = [NSKeyedUnarchiver unarchivedObjectOfClass:[Human class] fromData:data1 error:&error1];
    if (error1) {
        NSLog(@"解档数据失败,失败的原因是%@",error1);
    } else {
        NSLog(@"解档数据成功");
        NSLog(@"human name = %@,age = %ld",human1.name,human1.age);
    }
}

运行成功,点击解档,可以读取相应的内容

使用实例方法归档和解档

这个归档的路径使用path2
归档的代码为:

- (void)archiveData {
     NSLog(@"开始归档数据");
    Human *human = [[Human alloc] init];
    human.name = @"落叶兮兮";
    human.age = 24;
//第二种使用NSKeyArchiver的实例方法,编码时使用相应的键值,然后将编码后的数据写入执行的路径中
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
    [archiver encodeObject:human forKey:@"Human"];
    [archiver finishEncoding];
    NSLog(@"NSKeyArchiver编码的数据为%@",archiver.encodedData);
    [archiver.encodedData writeToFile:self.path2 atomically:YES];
    NSLog(@"归档结束");
}

解档的代码为:(注意解档时的键值要和归档的键值保持一致)

 //使用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(@"解档数据失败,失败的原因是%@",error2);
    } else {
        NSLog(@"解档数据成功");
        NSLog(@"human name = %@,age = %ld",human2.name,human2.age);
    }

运行后,可以查看到相应的文件


image.png

而且,来年各种功能方法存储的是一样的内容,data1文件的大小是243kb,data2文件的大小是244kb,或许就是因为data2存储时设置了键值“Human”

总结

最终存储后的效果图为:


image.png

Demo地址
对应的文件是Human.m和ArchiveViewController.m

iOS开发中数据持久化总结(一);
iOS开发中数据持久化总结(二):NSUserDefault实现数据存储
ios开发中数据持久化总结(三):NSKeyArchive归档解档的实现
ios开发中数据持久化总结(四):使用FMDataBase存储数据

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容