• iOS学习笔记: 初级数据持久化 归档与解档 和序列化及反序列化


    1>沙盒机制 

    iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等。
     
     1.1、每个应用程序都有自己的存储空间
     1.2、应用程序不能翻过自己的围墙去访问别的存储空间的内容
     1.3、应用程序请求的数据都要通过权限检测,假如不符合条件的话,不会被放行。  
     
    2>沙盒机构
    默认情况下,每个沙盒含有三个文件夹:Document, LIbrary和tmp, ios应用只能在自己的沙盒里读写文件
    Documents:苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候 和备份到iCloud的时候会包括此目录

    Library:存储程序的默认设置或其它状态信息;
     
    Library/Caches:存放缓存文件(比如图片什么的),iTunes不会备份此目录,此目录下文件不会在应用退出删除
    Library/Preference: 存放一些轻量数据, 如用户设置, 用户名/密码 等;
     
    tmp:提供一个即时创建临时文件的地方。
     
    .app文件 :开发过程中的文件, 包含所有的代码和资源 
     
    3>简单写入文件
    以NSString为例:
    第一步:获取要写入的文件夹路径,放在Document文件夹
    1 NSArray *bundlePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //nssearch是个C语言函数, 找到Document文件夹的路径,返回一个数组, 数组中的只存储了一个元素即文件夹的路径
    2 NSString *path = bundlePath.lastObject; // 取出数组中的路径

    第二步:在Document文件夹里创建文件

    1 path = [path stringByAppendingPathComponent:@"string.txt"]; // 给要创建的文件起个名字

    第三步:写入文件

     1 NSArray *bundlePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
     2     NSString *path = bundlePath.lastObject;
     3     path = [path stringByAppendingString:@"/string.txt”];
     4     //或者: path = [path stringByAppendingPathComponent:@"string.txt"];
     5     
     6     // 字符串
     7     NSString *str = @"这是我写入的字符串";
     8     NSError *error = nil;
     9     BOOL judge = [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; 
    10     if (judge) {
    11         NSLog(@"存储成功");
    12     } else {
    13         NSLog(@"error == %@", error);
    14     }

    其他一些默认支持直接写入文件的类型是:

    NSDictionary

    NSArray

    NSDate等, 更多在这里: NSUserDefaults Class Reference

    4>自定义对象要存到文件中的话,需要把自定义对象转换成NSData,让后利用NSUserDefault区保存NSData.

    将自定义对象转换成NSData, 首先对象本身需要遵循<NSCoding>协议并实现其中的两个方法:

    1 - (void)encodeWithCoder:(NSCoder *)aCoder
    2 { // 编码,或者叫序列化,将数据编码成二进制格式
    3     [aCoder encodeObject:_imgName forKey:kImageName];
    4     [aCoder encodeObject:_booksName forKey:kBookName];
    5     [aCoder encodeObject:_authorsName forKey:kAuthorName];
    6 }

    • – initWithCoder::解码
    • 1 - (id)initWithCoder:(NSCoder *)aDecoder
      2 {
      3     if (self = [super init]) {
      4         self.imgName = [aDecoder decodeObjectForKey:kImageName];
      5         self.booksName = [aDecoder decodeObjectForKey:kBookName];
      6         self.authorsName = [aDecoder decodeObjectForKey:kAuthorName];
      7     }
      8     return self;
      9 }

      实现了这两个方法的对象才可以正确转换成NSData并成功写到文件中, 把自定义对象转换成NSData用到的方法是Archive, 书上翻译叫归档 , 对应的解档的方法时Unarchive, 我觉得有点像压缩和解压缩吧.....

    • 对应的方法时:
    • NSKeyedArchiver class 的 +archiveDataWithRootObject:
    • NSKeyedUnarchiver class 的 + unarchiveObjectWithData: 

    当使用[NSKeyedArchiver archiveDataWithRootObject:XXX]将自定义对象归档时,会执行到对象中的 encodeWithCoder方法将对象中的数据编码 , 就可以得到NSData对象, 在保存到NSUserDefault里面; 相应的, 当从NSUserDefault中读取出保存的NSData后,  再调用[NSKeyedUnarchiver unarchiveObjectWithData:data]方法解码NSData, 会自动调用到对象内部的 initWithCoder方法, 将NSData解码为对应的对象;

    归档写入文件

    1 NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    2         path = [path stringByAppendingPathComponent:kFileName];
    3         MyBook *myBook =[[MyBook alloc] init]; 
    4         NSData *data = [NSKeyedArchiver archivedDataWithRootObject:myBook];
    5         [data writeToFile:path atomically:YES];

    读出文件解档

    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        path = [path stringByAppendingPathComponent:kFileName];
        NSData *data = [NSData dataWithContentsOfFile:path];
        MyBook *myBook = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    上面的方法不仅对单个对象适用, 对于存储自定义对象的数组,字典也适用, 因为系统的集合类比如NSArray也遵循了<

    NSSecureCoding>协议, 感觉应该和<NSCoding>差不多,所以当适用NSKeyedArchiver讲一个保存自定义对象的NSArray数组编码为NSData时, 内部会先调用NSArray的encodeWithCoder, 解码后发现内部都是自定义对象, 然后就分别针对每个自定义对象调用该对象内部的encodeWithCoder方法 , 这样就将一个保存自定义对象的数组转换为了NSData, 相应的解码过程也是差不多, 从NSData解码出NSArray数组时, 先调用NSArray的initWithCoder, 然后针对每个自定义对象调用initWithCoder, 最后解码出一个 自定义对象的数组.

    >

  • 相关阅读:
    【转】jQuery学习
    Eclipse工作空间的缺省字符编码问题
    BS与CS的区别
    内部类的作用
    test
    Delphi制作关不掉的程序
    屏蔽指定按钮
    实现拖动无标题窗口的5种方法
    Sql服务器及数据库枚举
    Delphi调用SQL分页存储过程实例
  • 原文地址:https://www.cnblogs.com/sexyBoBo/p/3780588.html
Copyright © 2020-2023  润新知