UI(十六)数据持久化和归档NSCoding序列化

#pragma mark---目录---

 1、两个目录:

①、沙盒 (有三个文件夹 docments temp library)

②、bundle 在运行的时候 只能读数据 写不进去数据

 2、读取路径方式

 bundle目录:[NSBundle mainBundle]

 根目录:NSHomeDirectory()

 tmp:NSTemporaryDirectory()


 ①、查找路径数组

NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)

 ②、找到指定路径

 取第一个或最后一个元素

 Documents:NSDocumentDirectory

 library:NSLibraryDirectory

 Caches:NSCachesDirectory


 读写文件

 数组 字典 字符串

 write

 ContentsOfFile


 [数组对象 writeToFile:path atomically:YES]

 [字典对象 writeToFile:path atomically:YES]

 [字符串对象 writeToFile:path atomically:YESencoding:NSUTF8StringEncoding error:nil]


 [NSArray arrayWithContentsOfFile:path]

 [NSDictionary dictionaryWithContentsOfFile:path]

[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]

 #pragma mark---正文---

 数据持久化:把闪存上的数据以文件的形式保存下来(保存到磁盘)它的目的是为了保存数据

 1、plist

 2、NSUserDefaults

 3、归档 NSCoding 序列化

 4、sqlite(数据库)

 5、coreData(苹果专有数据库)


 路径:文件存储的位置

 ios专有的沙盒机制:bandBox  IOS的应用程序里,每一个应用程序只能够读取写入本应用程序的沙盒目录

 沙盒的路径->应用程序根目录

 NSLog(@"%@",NSHomeDirectory());打印根目录


沙盒目录的组成:

 1、Documents:可以开放读取写入的权限->里面所有的文件都可以导出或者拖进去->不要放一些隐私的文件

 怎样打开? 

    info.plist文件里面添加 Application supports iTunes file sharing 把这个key对应的值改成YES就可以分享Documents目录

 2、Library:存放配置信息或者数据库资源文件

 3、tmp:临时文件存储的地方 隔一段时间会清除一次(可以设置)->不能放重要的文件(数据库)

 bundle目录:应用程序右键显示包内容的目录 不允许应用程序在运行的时候写入任何数据


 #pragma mark---查找各个目录路径的方式:---

 根目录:NSHomeDirectory()

 bundle目录:[NSBundle mainBundle]

 tmp目录: NSTemporaryDirectory()

 #pragma mark---查找特殊的几个目录---

 Library目录、Documents目录、NSCachesDirectory:

 (1)、找到根目录--NSHomeDirectory() 拼接到Library目录

 ①通过拼接字符串拼接路径

NSString *path = [NSHomeDirectory() stringByAppendingString:@"/Library"];

NSLog(@"%@",path);

 ②专门用于拼接路径的方式

 路径是以“/”来区分的 如果用拼接字符串的方式拼接路径就必须加“/”

 如果用拼接路径的方式拼接路径就不能加“/”

NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library"];

NSLog(@"%@",path);

 (2)、查找用户应用程序的范围 查找Library目录

 记:查找目录会得到一个数组 Search(查找)

 ① 先找到某个路径的数组

NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);


     NSSearchPathForDirectoriesInDomains(要查找的路径, 要搜索的区域范围, 是不是允许获得扩展的目录);

 ② 获得数组里面的第一个或者最后一个目录(只有一个元素),就是要查找的目录

 NSString *path3 = [pathList lastObject];

NSLog(@"%@",path3);


 #pragma mark---写入读取文件:---

 字典、数组都有读取写入文件的方法

 1、写入到plist文件里面

 2、

 数组读取文件

 arrayWithContentsOfFile:(NSString *)path

 initWithContentsOfFile:(NSString *)path

 数组写入内容

 - (BOOL)writeToFile:文件路径 atomically:(BOOL)useAuxiliaryFile

**atomically 如果设置成YES 不会直接写入到指定文件 先写入到一个临时文件 暂存一下 当写入完毕才会存入到指定文件 如果遇到(断电 闪退 来电话...)就会删除临时文件 不去写入到指定文件 防止写入数据不完整 在使用的时候出现崩溃

 如果设置成NO 不管任何情况 都会写入


 字典读取文件

 dictionaryWithContentsOfFile:(NSString *)path

 initWithContentsOfFile:(NSString *)path

 字典写入文件

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile


 字符串读取文件

  initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error

 stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error


NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

 字符串写入文件

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error


 NSError *error;

[content writeToFile:path atomically:YESencoding:NSUTF8StringEncoding error:&error];

--------------------------------------------------------------------

#pragma mark---归档---

*归档->数据持久化的方式->加密(把文件加密《不是把数据加密》)

*归档分为:

 1、存储数据(编码、序列化、归档过程)

 2、读取数据(解码、反序列化、解归档过程)


*可以归档的对象:必须遵守归档协议(NSSecureCoding遵守NSCoding)、实现协议方法


*除了NSObject未实现归档协议 其他实现了协议的类 都可以归档(UIViewController、UIView...)


归档类名:NSKeyedArchiver

解归档类名:NSKeyedUnarchiver


*归档、解归档 都是通过key来实现的

*在归档、解归档的时候 key一定要对应(尽量和对象名相同)

#pragma mark-----归档的步骤--------

1、写存储归档文件的路径

NSArray *searchList = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);

 *归档文件的尾缀尽量用 .archiver

NSString *path = [[searchList lastObject]stringByAppendingPathComponent:@"list.archiver"];

2、准备要归档的数据

NSArray *list = @[@{@"name":@"小明", @"age":@(18), @"height":@(18.5)}];

3、开始归档

*把一个Object(支持归档)的数据 以归档的形式存储到指定位置

 + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;

*支持归档协议的对象 系统帮忙对他进行了编码

 BOOL isSuccess = [NSKeyedArchiver archiveRootObject:list toFile:path];

 if (isSuccess) {

NSLog(@"%@",path);

    }

#pragma mark-----解归档的步骤------

1、归档文件路径

2、开始解归档

 + (nullable id)unarchiveObjectWithFile:(NSString *)path

    NSArray *list = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

#pragma mark---NSData二进制的类---

*NSData 二进制的类 可以把文件或者数据转成二进制的对象

#pragma mark---多种数据归档步骤---

1、存储路径

NSArray *searchList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

 NSString *path = [[searchList lastObject]stringByAppendingPathComponent:@"user.archiver"];

2、初始化一个可变的二进制对象 **NSMutableData 同时准备要归档的数据

NSString *name = @"mary";

 NSInteger age = 18;

 float height = 172.5;


 NSMutableData *Data = [NSMutableData data];

3、归档等待写入数据的二进制对象(要把二进制对象写入到文件)->让归档对象帮他写入


     NSKeyedArchiver *arc = [[NSKeyedArchiver alloc]initForWritingWithMutableData:Data];

4、使用归档对象 对要归档的数据进行编码(同时写入到二进制对象-系统帮咱们操作)(编码结束就会把编码后的数据写入二进制对象)

*编码:encode 解码:decode

*要用对应的数据类型进行编码

[arc encodeObject:name forKey:@"name"];

[arc encodeInteger:age forKey:@"age"];

[arc encodeFloat:height forKey:@"height"];

5、编码结束

*把编码之后数据写入到二进制对象

     [arc finishEncoding];

6、把二进制对象存储到指定位置

 BOOL isSuccess = [Data writeToFile:path atomically:YES];

 if (isSuccess) {

NSLog(@"%@",path);

#pragma mark---多种解归档---

 **decode 解码

- (instancetype)initForReadingWithData:(NSData *)data

1、归档文件路径

2、使用data读取数据 准备解归档data里面的数据

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:[NSData dataWithContentsOfFile:path]];

3、解归档数据 用对应的数据类型接收

 NSString *name = [unarchiver decodeObjectForKey:@"name"];

 NSInteger age = [unarchiver decodeIntegerForKey:@"age"];

 float height = [unarchiver decodeFloatForKey:@"height"];

 NSLog(@"%@  %ld  %f",name,age,height);


#pragma mark---*自定义归档*---

自定义归档->有些数据不能归档->让他遵守归档协议(NSCoding)->

 归档、解归档都与第一种方式相同

userModel *user = [[userModel alloc]init];

user.name = @"江儿";

user.age = 18;

user.height = 165.5;


 NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"user.archiver"];

 BOOL isOK = [NSKeyedArchiver archiveRootObject:user toFile:path];

 if (isOK) {

NSLog(@"%@",path);

    }



 userModel *userMode= [NSKeyedUnarchiverunarchiveObjectWithFile:path];


 NSLog(@"%@ %ld %f",userMode.name,userMode.age,userMode.height);


当在归档位置(viewController中)调用[NSKeyedArchiver archiveRootObject:XXX toFile:XXX]; 会自动调用encodeWithCoder:这个代理方法

使用**归档方法对对象归档的时候 会调用这个方法

- (void)encodeWithCoder:(NSCoder *)aCoder{

    aCoder就是系统传过来的NSKeyedArchiver实例化出来的对象

[aCoder encodeObject:self.name forKey:@"name"];

[aCoder encodeInteger:self.age forKey:@"age"];

[aCoder encodeFloat:self.height forKey:@"height"];

}


使用**解归档方法对对象解归档的时候 会调用这个方法

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{

 只要是构造方法先把创建对象的方法补全

 //self = [super init];

 //if (self) {

 //}

 //return self;


 self = [super init];

 if (self) {

 当使用解归档方法的时候 系统会自动调用initWithCoder:这个方法 系统会帮咱们创建一个对象

 之前的对象的数据保存在 归档文件里面

 在解归档的时候 还原数据 并且把还原的数据赋值给这个对象->现在这个对象的数据跟原来归档的数据是一样的

 self.name = [aDecoder decodeObjectForKey:@"name"];

 self.age = [aDecoder decodeIntegerForKey:@"age"];

 self.height = [aDecoder decodeFloatForKey:@"height"];


    }


 return self;

}

你可能感兴趣的:(UI(十六)数据持久化和归档NSCoding序列化)