UI 16 数据持久化

就是将数据保存在本地.
归档和返归档.
苹果手机为了保证自己数据上的绝对安全.设计了沙盒文件,每一个应用程序都配备了自己的沙河文件,每一次运行,文件夹的名字就会变成没有任何规律的字符串.
第一个参数: 当前前往哪一个文件夹,前往Documents文件用NSDocumentsDirectory, 64行. 还可以前往缓存Caches,对应68行.
第二个参数: 访问的文件夹类型,指定访问的是用户文件夹.
第三个参数: 绝对路径(YES); 相对路径(NO);
绝对路径是给系统来使用的, 系统可以通过当前的路径找到文件夹,我们在操作文件的时候都会用绝对路径;
相对路径只会把前往的文件夹显示,其他部分是~,告诉程序员要去哪个文件夹.

NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSLog(@"%@",sandBox[0]);   

沙盒中一共有3个文件.
1.Documents文件: 主要用来存储用户想要储存的一些信息,比如收藏的信息或者自己设置的一些内容,所以我们做收藏功能一般往这个文件夹里面写文件.
2.Library文件夹是方便程序开发者使用的,主要操作他的两个文件夹,caches和Preferences.
caches: 用来保存缓存文件,SDWebImage会把图片加到缓存文件中,所以清除缓存功能就是把这个文件夹删除.
Preferences 一般用来保存程序猿设置的信息,比如NSUserDefaults就会把数据存在这个文件夹中.
3.tmp文件: 一般存放临时内容.
之前在沙河中还有一个文件,.app文件,在新版本里已经被移除.

要把简单对象写入本地, 简单对象指的是NSString, NSArray等.

//1. 先通过数组获取沙盒路径.
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    // 从数组中获取沙盒路径.
    NSString *sandBoxPath = sandBox[0];
    // 给你要保存的文件拼出来路径, 因为Documents里什么都没有.拼接方式有两种:

//    NSString *documentPath1 = [sandBoxPath stringByAppendingString:@"/刘鑫奇.txt"];
//    
    NSString *documentPath2 = [sandBoxPath stringByAppendingPathComponent:@"刘鑫奇.plist"];
//     NSLog(@" 1路径 :%@",documentPath1);
     NSLog(@" 2路径 :%@",documentPath2);
    NSString *str = @"今天你要嫁给我吗?,lalaallalallalallala";

    // 把字符串写入到本地.
    // 第一个参数: 文件要保存的路径
    // 第二个参数: 对文件进行保护,YES
    // 第三个参数: 编码
    // 第四个参数: 错误信息.
    [str writeToFile:documentPath2 atomically:YES encoding:NSUTF8StringEncoding error:nil];
    // 如果路径下有对应的文件,则会把原来的文件覆盖,如果没有则创建一个新文件.

     //将沙盒文件读粗来
    NSString *tempStr = [NSString stringWithContentsOfFile:documentPath2 encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",tempStr);
//2.数组写入到本地
    NSArray *arr = @[@"1",@"2",@"3",@"4",@"5"];
    //1. 通过数组获取沙盒地址.
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    //用字符串保存沙盒路径
    NSString *sandBoxPath = sandBox[0];
    // 给药写入文件拼接路径
    NSString *arrPath = [sandBoxPath stringByAppendingPathComponent:@"arr.plist"];
    // 将数组写入本地
    [arr writeToFile:arrPath atomically:YES];
    NSLog(@"%@",arrPath);
    // 把数组从本地读出来

    NSArray *arrPlist = [NSArray arrayWithContentsOfFile:arrPath];
    NSLog(@"%@",arrPlist);
 // 把字典写入到本地.
    NSDictionary *dic = @{@"男":@"刘鑫奇",@"女":@"高薪茹",@"孩":@"刘伊茹"};
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *sandBoxPath = sandBox[0];
    NSString *dicPath = [sandBoxPath stringByAppendingPathComponent:@"dic.plist"];
    [dic writeToFile:dicPath atomically:YES];

    // 读取
    NSDictionary *tempDic = [NSDictionary dictionaryWithContentsOfFile:dicPath];
    for (NSString *key in tempDic) {
         NSLog(@"%@:%@",key,tempDic[key]);
    }

那么? 要是想要将一个自己写的model类写入本地呢?
如果想要实现归档和反归档的操作需要先签订一个协议 NSCoding. 有两个必须实现的方法.
我的model类是student

@interface StudentModel : NSObject<NSCoding>

@property(nonatomic, copy)NSString *name;
@property(nonatomic, copy)NSString *sex;
@property(nonatomic, copy)NSString *hobby;
@property(nonatomic, assign)NSInteger age;
// 针对这四条写一个自定义初始化.
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age;

+ (StudentModel *)StudentWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age;

@end
#import "StudentModel.h"

@implementation StudentModel
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age{
    self = [super init];
    if (self){
    self.name  = name;
    self.sex = sex;
    self.hobby = hobby;
    self.age = age;
    }
    return self;
}

+ (StudentModel *)StudentWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age{
    StudentModel *model = [[StudentModel alloc] initWithName:name sex:sex hobby:hobby age:age];
    return model;
}

#pragma mark 签订完NSCoding协议之后,需要实现两个协议方法,一个是归档的时候使用,一个是反归档的时候使用.
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.name forKey:@"姓名"];
    [aCoder encodeObject:self.sex forKey:@"性别"];
    [aCoder encodeObject:self.hobby forKey:@"爱好"];
    [aCoder encodeInteger:self.age forKey:@"年龄"];

    // 使用encode方法要和数据的类型相互匹配.  
}

- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        // 把数据根据之前的Key反编译过来, 再对self赋值
       self.name = [aDecoder decodeObjectForKey:@"姓名"];
       self.hobby = [aDecoder decodeObjectForKey:@"爱好"];
       self.sex = [aDecoder decodeObjectForKey:@"性别"];
       self.age = [aDecoder decodeIntForKey:@"年龄"];  
    }
    return self;
}

这些工作做好后, 我们就可以将复杂对象写入本地啦.

    // 把复杂对象写入本地, 需要签订NSCoding协议
    StudentModel *stu = [StudentModel StudentWithName:@"刘鑫狗儿" sex:@"男" hobby:@"高高" age:23];
    // 通过数组获取沙盒路径
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *sandBoxPath = sandBox[0];
    // 接下来拼接存放对象的文件夹路径,这个文件的扩展名可以是任意的.
    NSString *stuPath = [sandBoxPath stringByAppendingPathComponent:@"学生信息.avi"];
    // 对对象进行归档.
     // 第一个参数: 要实施归档的对象.
     // 第二个参数: 路径.
    [NSKeyedArchiver archiveRootObject:stu toFile:stuPath];
    NSLog(@"%@",stuPath);

    // 返归档
    StudentModel *newStu = [NSKeyedUnarchiver unarchiveObjectWithFile:stuPath];
    NSLog(@"%@",newStu.name);

那么, 把复杂对象装入数组中保存呢?

 // 把复杂对象存到数组中,保存.
    StudentModel *stu1 = [StudentModel StudentWithName:@"刘鑫狗1" sex:@"男1" hobby:@"高薪茹1" age:23];
    StudentModel *stu2 = [StudentModel StudentWithName:@"刘鑫狗2" sex:@"男2" hobby:@"高薪茹2" age:23];
    StudentModel *stu3 = [StudentModel StudentWithName:@"刘鑫狗3" sex:@"男3" hobby:@"高薪茹3" age:23];
    StudentModel *stu4 = [StudentModel StudentWithName:@"刘鑫狗4" sex:@"男4" hobby:@"高薪茹4" age:23];
    NSArray *arr = @[stu1,stu2,stu3,stu4];
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *sandBoxPath = sandBox[0];
    NSString *arrPath = [sandBoxPath stringByAppendingPathComponent:@"数组学生.avi"];

    [NSKeyedArchiver archiveRootObject:arr toFile:arrPath];
    NSLog(@"%@",arrPath);

    // 反归档: 遍历学生姓名.
    NSArray *newArr = [NSKeyedUnarchiver unarchiveObjectWithFile:arrPath];
    for (StudentModel *stu in newArr) {
           NSLog(@"姓名:%@  爱好:%@",stu.name,stu.hobby);
    }

* warning 总结: 数据持久化的步骤:
// 指定前往沙盒的哪一个文件夹.
// 用字符处接受沙盒路径.
// 拼接文件路径.
// 存入本地或者归档.*

如果复杂对象想要归档. 需要签订NSCoding协议,并且实现两个协议方法,放在数组里的复杂对象归档也要签协议.

那么, 想要添加一个文件夹呢?

#warning 文件管理者对文件夹进行操作
    NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *sandBoxPath = sandBox[0];
    // 创建一个文件管理者
    NSFileManager *manager = [NSFileManager defaultManager];

    // 给要创建的文件夹拼接一个路径
    NSString *newFilePath = [sandBoxPath stringByAppendingPathComponent:@"刘鑫奇"];
    // 文件夹不需要有扩展名.
    // 通过manager进行文件夹的创建.
    [manager createDirectoryAtPath:newFilePath withIntermediateDirectories:YES attributes:nil error:nil];
    NSLog(@"%@",newFilePath);

    NSString *str = @"哈哈哈哈哈哈哈";
    NSString *strPath = [newFilePath stringByAppendingPathComponent:@"str.txt"];
    [str writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",strPath);

    // 读取
    NSString *newStr = [NSString stringWithContentsOfFile:strPath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",newStr);

    // 删除文件夹
    [manager removeItemAtPath:newFilePath error:nil];

如此, 我们就能够删除caches文件了.

// 删除Caches
    NSArray *SandBox = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesPath = SandBox[0];
    NSLog(@"%@",cachesPath);
    [manager removeItemAtPath:cachesPath error:nil];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值