iOS 数据归档解档

简介

本篇文章使用NSKeyedArchiver和NSKeyedUnarchiver进行iOS的归档解档
这是之前写的一篇文章了,最近在复习深复制发现有的方法已经随着iOS版本的更新淘汰了,这篇文章也重新写一下吧,有的方法还是没有找到合适的,如果有伙伴看到这里敬请指点

  • 归档:即将数据写入文件里。一般我们app的数据都是在内存里,只要app关闭,数据就会丢失。但是将数据保存在文件里,就能将数据保存至本地,不管app关闭还是重启设备,下次启动app的时候都能够读出来
  • 解档:就是将保存的数据从文件中读出来在程序中使用
  • 关于沙盒可以参考:iOS开发关于沙盒

普通数组的归档解档

归档

  • 首先获取文件归档路径
  • 使用方法 archivedDataWithRootObject: requiringSecureCoding: error: 将模型数组转成data数组 writeToFile: atomically: 将data数组写入文件,返回值为BOOL型,可以查看是否写入成功
  • 方法介绍:
    P1: 要归档的对象
    P2:一个布尔值,指示是否所有编码对象都必须符合NSSecureCoding
    P3:返回的错误
	//沙盒根目录
    NSString *docPath = NSHomeDirectory();
    //完整的文件路径
    NSString *path = [docPath stringByAppendingPathComponent:@"Documents/numbers.plist"];
    NSArray *numbers = @[@"one",@"two"];
    
    //将数据归档到path文件路径里面
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:numbers requiringSecureCoding:NO error:nil];
    BOOL success = [data writeToFile:path atomically:NO];
    
    if (success) {
        NSLog(@"文件归档成功");
    } else {
        NSLog(@"文件归档失败");
    }

解档

  • 首先获取文件路径
  • 使用方法 dataWithContentsOfFile: 将文件数据化
  • 使用方法 unarchivedObjectOfClass: fromData: error: 转化数据,读取内容
	NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //完整的文件路径
    NSString *path = [docPath stringByAppendingPathComponent:@"numbers.plist"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSArray *array = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:nil];
    NSLog(@"%@", array);

在这里插入图片描述

自定义对象的归档解档

上面的例子,归档的内容都是系统Foundation框架提供的类以及一些基本的数据类型。
Foundation框架提供的类都是实现了NSCoding协议的,所以能够直接进行归档。
如果我们自己自定义了一个类,例如ModelStudent类,是无法能够直接将这个类进行归档操作的。
如果想要对自定义的类创建出来的对象进行归档,我们需要先实现NSCoding协议。
如果没实现NSCoding协议及其方法,就会Crash:
在这里插入图片描述

ModelStudent.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ModelStudent : NSObject<NSCoding>

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

@end

NS_ASSUME_NONNULL_END

ModelStudent.m

#import "ModelStudent.h"

@implementation ModelStudent

- (id)copyWithZone:(NSZone *)zone {
    ModelStudent *student = [[ModelStudent alloc] init];
    student.name = self.name;
    student.age = self.age;
    student.sex = self.sex;
    return student;
}

//NSCoding协议方法:将需要归档的属性进行归档
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeInteger:self.age forKey:@"age"];
    [coder encodeObject:self.name forKey:@"name"];
}

//NSCoding协议方法:将需要解档的属性进行解档
- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        self.name = [coder decodeObjectForKey:@"name"];
        self.age = [coder decodeIntegerForKey:@"age"];
    }
    return self;
}

@end

归档

此处使用另一种获取目录方法

	 ModelStudent *student1 = [[ModelStudent alloc] init];
     student1.name = @"111";
     student1.age = 10;
     student1.sex = 1;
    
     //沙盒ducument目录
     NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
     //完整的文件路径
     NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
     
     //将数据归档到path文件路径里面
     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student1 requiringSecureCoding:NO error:nil];
     BOOL success = [data writeToFile:path atomically:YES];
     
     if (success) {
         NSLog(@"归档成功");
     }else {
         NSLog(@"归档失败");
     }

解档

	NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
    // 这个方法是过期的,但是目前我没有找到可以代替的方法
    ModelStudent *student = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    NSLog(@"student's name = %@, student's grade = %lu", student.name, student.age);

在这里插入图片描述

归档失败

  • 第一种可能:文件夹不存在
    如果文件夹不存在,则创建一个
    //文件夹是否存在
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:dir isDirectory:nil];
    if (!fileExists) {
        NSLog(@"文件夹不存在");
        NSError *error = nil;
        [[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:&error];
        if (error) {
            NSLog(@"error == %@", error.description);
        } else {
            NSLog(@"success");
        }
    }
  • 第二种可能:没有写入权限
    有些不熟悉的人可能会遇到这个问题:我在模拟器上归档操作是成功的,可是在真机上运行的时候却归档失败了。到底是什么原因?
    这个就是遇到了写权限的问题了。在模拟器上,因为是写在电脑上面的路径的,所以这个路径我们有写权限。但是真机不一样,真机上我们一般情况下只能操作沙盒路径里面文件夹。无法在其他的地方写文件。
    沙盒根目录也没有写入权限,我们一般在Documents目录写
    //查看是否有写入权限
    if (![[NSFileManager defaultManager] isWritableFileAtPath:dir]) {
        NSLog(@"目录无写入权限");
    }

文章参考文献:【iOS】数据持久化:使用NSKeyedArchiver进行数据归档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值