zoukankan      html  css  js  c++  java
  • 数据存储的三种方式

     
    读取info.plist文件:
     NSDictionary *infoDict =  [NSBundle mainBundle].infoDictionary;
     NSString *version = infoDict[@"CFBundleVersion"];
    一,属性列表
    属性列表即plist文件,实质是xml文件。 

    注意点:

      1. 根节点只能是NSArray或者NSDictionary 
      2. 如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中
    • 将一个NSDictionary对象归档到一个plist属性列表中
    // 将数据封装成字典
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:@"母鸡" forKey:@"name"];
    [dict setObject:@"15013141314" forKey:@"phone"];
    [dict setObject:@"27" forKey:@"age"];
    // 将字典持久化到Documents/stu.plist文件中
    [dict writeToFile:path atomically:YES];
     
     
    二,偏好设置
         用于保存APP的设置,例如是否记住密码、是否接受推送、保存字体大小等。
    // 保存数据
    -(void)saveData
    {
        // 1.获取偏好设置
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        // 2.保存数据
        [userDefaults setObject:@"传智播客" forKey:@"itcastKey"];
        [userDefaults setBool:YES forKey:@"isGoodKey"];
     
    /*注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入
    */ 
      // 3.同步数据(iOS8)
        [userDefaults synchronize];
    }

    // 读取数据
    -(void)readData
    {
        // 1.获取偏好设置
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        // 2.读取数据
        NSLog(@"%@",[userDefaults objectForKey:@"itcastKey"]);
    }
     
     
    三,归档可以将任意类型的对象,编码后以二进制的形式保存。
    在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦;
    偏好设置(将所有的东西都保存在同一个文件夹下面,且主要用于存储应用的设置信息)
    归档优势:因为前两者都有一个致命的缺陷,只能存储常用的类型。归档可以实现把自定义的对象存放在文件中。
     
    注意点:
    1. 需要归档的自定义类,必须实现<NSCoding>协议,告诉系统需要归档和解档哪些属性。
    2. 若对象的属性中有自定义类型,则该类也需要实现<NSCoding>协议。
    // 保存数据
    -(void)saveData
    {
        // 1.创建对象
        CZPerson *person = [CZPerson new];
        person.name = @"Jack";
        person.age = 18;

        // 2.实现<NSCoding>协议

        // 3.获取文件路径
        NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];

        // 4.编码并保存(归档)
        [NSKeyedArchiver archiveRootObject:person toFile:filePath];
    }

    // 读取数据
    -(void)readData
    {
        // 1.获取文件路径
        NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filePath = [documents stringByAppendingPathComponent:@"person.data"];

        // 2.解档
        CZPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

        NSLog(@"%@",person.name);
    }
     
     实现<NSCoding>协议
      • encodeWithCoder什么时候调用:对象归档时候调用
     
      • encodeWithCoder作用:告诉系统对象里的哪些属性需要归档,怎么去归档,根据一个key去归档,目的就是以后取的时候,也根据这个key去取数据。
    // 编码
    -(void)encodeWithCoder:(NSCoder *)aCoder
    {
        [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeInteger:_age forKey:@"age"];
    }
      • initWithCoder作用:告诉系统对象里的哪些属性需要解档,怎么去解档,根据之前存储的key去解档
        • initWithCoder是一个初始化方法,需要先初始化父类的,但是不能调用[super initWithCoder:],因为父类NSObject没有遵守NSCoding协议。
        3> initWithCoder什么时候需要调用[super initWithCoder:]
        • initWithCoder原理:只要解析文件就会调用,xib,storyboard都是文件,因此只要解析这两个文件,就会调用initWithCoder。
        • 因此如果在storyboard使用自定义view,重写initWithCoder方法,一定要调用[super initWithCoder:],因为只有系统才知道怎么解析storyboard,如果没有调用,就解析不了这个文件。
    // 解码,实例化
    -(instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        if (self = [super init])
        {//将对象的一些属性保存,没有设置的属性不作保存
            _name = [aDecoder decodeObjectForKey:@"name"];
            _age = [aDecoder decodeIntegerForKey:@"age"];
        }
        return self;
    }
     

    两个方法的区别与使用场景
    /// 解归档 : 这个方法是把视图从bundle加载到内存.视图的frame可能不准
    //- (instancetype)initWithCoder:(NSCoder *)aDecoder
    //{
    //    if (self = [super initWithCoder:aDecoder]) {
    //        NSLog(@"%s",__func__);
    //    }
    //    return self;
    //}

    /// 视图被唤醒的方法.在这个方法里面可以拿到准确frame的视图
    - (void)awakeFromNib
    {
     
    }
     
    //读取JSON文件,转模型
    + (NSArray *)projects {
        // 1. 文件路径
        NSString *path = [[NSBundle mainBundle] pathForResource:@"more_project.json" ofType:nil];
        // 2. 读取文件内容 -  二进制数据
        NSData *data = [NSData dataWithContentsOfFile:path];
        // 3. 解析JSON 专门用来解析JSON的类 NSJSONSerialization
        /**
         看到options先传0.没有达到效果再来看枚举值
         */
        NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        // 声明一个可变的数组
        NSMutableArray *projects = [NSMutableArray array];
        // 4. 遍历数据,把字典转成模型 - 使用block来遍历数组
        [json enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            CZProject *project = [CZProject projectWithDict:obj];
            [projects addObject:project];
        }];
    // 将可变数组,变成不可变 : 将线程不安全的类,变成了线程安全的类.同时,不可变的数组,外界不能修改的.
        return projects.copy;
    }
     
  • 相关阅读:
    C# 事务之SqlTransaction
    java获取字符串格式日期向前或向后n天的日期
    java中保留几位小数
    第一个androidAPP项目总结—ListView的上拉和下拉
    java中static作用详解
    第一个androidAPP项目总结—数据请求
    获取控件的高和宽
    Android学习笔记:如何设置ImageView中图片的显示方式
    TextView过长显示省略号, TextView文字中间加横线
    android中控件的使用
  • 原文地址:https://www.cnblogs.com/somethingWithiOS/p/5595053.html
Copyright © 2011-2022 走看看