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了

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

  • 相关阅读:
    题解 CF171G 【Mysterious numbers
    题解 P1157 【组合的输出】
    题解 P3955 【图书管理员】
    题解 P2036 【Perket】
    题解 CF837A 【Text Volume】
    题解 CF791A 【Bear and Big Brother】
    题解 CF747A 【Display Size】
    题解 P1332 【血色先锋队】
    题解 P2660 【zzc 种田】
    题解 P4470 【[BJWC2018]售票】
  • 原文地址:https://www.cnblogs.com/luseike/p/3775486.html
Copyright © 2011-2022 走看看