zoukankan      html  css  js  c++  java
  • IOS 数据存储

    IOS中数据存储一般分为以下几种方式

    1、XML属性列表(plist)归档
    2、preference(偏好设置)
    3、NSKeyedArchiver归档(NSCoding)
    4、SQLite3
    5、Core Data
    鄙人才疏,先扯扯前三种刚学的存储方式,做个总结以备复习使用
     
    1、首先了解沙盒的概念,他是应用的系统文件夹,每个应用的沙盒是相互独立的,不能彼此访问(IOS8打破了这一惯例)。谈到数据存储,就不得交代下数据存储在哪里,一般是存储在沙盒的几个文件中:
    Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录
    tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录
    Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据
    Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
     
    接下来尝试将数据存储在documents中,获取Documents目录有这么两个方法:

    1、NSString *home = NSHomeDirectory();

    2、NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

    方法1获取到了应用程序沙盒目录,进一步需要使用stringByAppendingString方法拼接出Documents的最终路径,这怎么说也有点繁琐。苹果给咱提供了第二种比较牛逼的方法,获取到的是一个Array对象,其实里面就一个文件夹,随意lastObject或firstObject都能靠谱的拿到,拼接个要存储到的文件名,直接write进去,直接看小弟的代码:

    NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // 拼接文件路径
        NSString *path = [doc stringByAppendingPathComponent:@"abc.plist"]
        ;
    
        NSArray *arr = @[@"luseike", @"25"];
        [arr writeToFile:path atomically:YES];
    

     documents中已经出现了abc.plist(啰嗦句,documents里面存的是plist文件,这个你肯定知道,它本质上是XML文件。plist文件中能存储系统自带的一些数据类型,比如NSArray、NSString、NSNumber……,也就是用writeToFile方法的对象)

    2、在来试试第二种存储方式吧,preference是专门用来存储应用程序的配置信息的。如果利用系统里的偏好设置来存储数据,默认是存储中Preference文件夹下面的,并且会将所有的数据保存到同一文件中。

    它具体的使用方法是利用NSUserDefaults对象,每个应用都有自己的UserDefault,代码如下:

    // 获取NSUserDefaults对象
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        // 保存数据(如果设置数据之后没有同步, 会在将来某一时间点自动将数据保存到Preferences文件夹下面)
        [defaults setObject:@"luseike" forKey:@"name"];
        [defaults setObject:@"man" forKey:@"gender"];
        [defaults setInteger:13 forKey:@"age"];
        [defaults setDouble:10.1 forKey:@"height"];
    

     preference下面存储的数据不会立即更新,你可以手动同步下,[defaults synchronize]; 轻松搞定。保存的时候是set进去的,读取的时候当然也要按照这个套路来才行,上代码:

    // 1.获取NSUserDefaults
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        // 2.通过NSUserDefaults获取保存的数据
        NSString *name = [defaults objectForKey:@"name"];
        int age = [defaults integerForKey:@"age"];
        NSLog(@"%@", name);
        NSLog(@"%d", age);
    

     苹果居然给我们提供了逆天的integerForKey,当然还有floatFor、doubleFor……

    3、上面这两种方式都只能存储系统自带的数据类型,如果要存我们自定义的数据类型,就有点尴尬了,这就不得不邪恶的搬出第三种方式了

    NSKeyedArchiver这哥们牛逼的很,自定义一个Person类,有name、age、height三个属性,来看看NSKeyedArchiver怎么存储

    // 1.创建对象
        /*
        NJPerson *p = [[NJPerson alloc] init];
        p.name = @"lnj";
        p.age = 28;
        p.height = 1.76;
         */
        
        NJStudent *stu = [[NJStudent alloc] init];
        stu.name = @"luseike";
        stu.age = 25;
        stu.height = 1.8;
        stu.weight = 60;
        
        // 2.获取文件路径
        NSString *docPath =  [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *path = [docPath stringByAppendingPathComponent:@"stu.xxoo"];
        NSLog(@"path = %@", path);
        
        // 3.将自定义对象保存到文件中
    //    [NSKeyedArchiver archiveRootObject:p toFile:path];
        [NSKeyedArchiver archiveRootObject:stu toFile:path];
    

     这么使用,有一个条件,那就是要存储的类型必须实现NSCoding协议里面定义的两个方法,这两个方法描述了如何对数据进行存储

    // 当将一个自定义对象保存到文件的时候就会调用该方法
    // 在该方法中说明如何存储自定义对象的属性
    // 也就说在该方法中说清楚存储自定义对象的哪些属性
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        NSLog(@"NJPerson encodeWithCoder");
        [encoder encodeObject:self.name forKey:@"name"];
        [encoder encodeInteger:self.age forKey:@"age"];
        [encoder encodeFloat:self.height forKey:@"heigth"];
    }
    
    // 当从文件中读取一个对象的时候就会调用该方法
    // 在该方法中说明如何读取保存在文件中的对象
    // 也就是说在该方法中说清楚怎么读取文件中的对象
    - (id)initWithCoder:(NSCoder *)decoder
    {
        NSLog(@"NJPerson initWithCoder");
        if (self = [super init]) {
            self.name = [decoder decodeObjectForKey:@"name"];
            self.age = [decoder decodeIntegerForKey:@"age"];
            self.height = [decoder decodeFloatForKey:@"heigth"];
        }
        return self;
    }
    

     还有一点需要注意,如果一个类继承了Person类,子类中添加的属性是保存不成功的,子类必须重写协议方法才可以。比如定义了继承Person类的Student类,新增weight属性,Student实现协议的代码如下

    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
        [super encodeWithCoder:aCoder];
        NSLog(@"NJStudent encodeWithCoder");
        [aCoder encodeFloat:self.weight forKey:@"weight"];
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        if (self = [super initWithCoder:aDecoder]) {
            NSLog(@"NJStudent initWithCoder");
            self.weight = [aDecoder decodeFloatForKey:@"weight"];
        }
        return self;
    }
    

     然后像保存Person一样的方式就能正常保存Student了

    先嘚瑟这么多,以后学习了新知识再补充,新手学习中,请勿拍砖,待续……

  • 相关阅读:
    day 80 视图家族
    day 79 drf 多表关联操作
    day 78 drf 序列化
    day 77 drf中请求、渲染、解析、异常、响应模块的二次封装
    day 76 drf
    python小知识
    请求 渲染 解析 异常 响应模块
    子组件
    vue基础(2)
    vue基础
  • 原文地址:https://www.cnblogs.com/luseike/p/3775486.html
Copyright © 2011-2022 走看看