iOS 数据存储

一、ios中数据存储方式

     * XML属性列表(plist)归档

            > plist全名是:Property List,属性列表文件。它是一种用来存储串行化后的对象的文件。属性列表文件的扩展名为.plist,因此通常被称为plist文件。文件是xml格式的。它是以key-value的形式来存储数据。

            > 可以用来存储用户设置,也可以用来存储一些需要经常用到而不经常改动的信息。

            > plist只能存储系统自带的一些常规的类, 也就是有writeToFile方法的对象才可以使用plist保存数据。例如:NSString、NSDictionary、NSArray、NSData、 NSNumber等类型

 

        * Preference(偏好设置)

            > 偏好设置本质也是 plist。

            > 偏好设置是专门用来保存应用程序的配置信息,比如保存用户名、密码、字体大小、是否自动登录等小数据量信息。

 

            > 一般情况不要在偏好设置中保存其他数据(比如图片数据,或者其他大文本数据)。如果利用系统的偏好设置来存储数据,默认就是存储在Preferences文件夹下面的,偏好设置会将所有的数据都保存到同一个文件中。

 

        * NSKeyedArchiver归档(NSCoding)

            > NSKeyedArchiver功能非常强大,使用它类进行对象(包括自定义的对象)序列化和反序列化。

              * 序列化简单的理解就是将对象保存到文件的过程。

              * 反序列化就是将从文件中读取对象的过程。

 

        * SQLite3 数据库

            > 比较出名的数据库有 MySql/Oracle/DB2/SqlServer/...这些大型数据库是用在 pc 电脑上的,不是用在手机上的。手机上开发用的是嵌入式微型数据库,就是SQLite数据库。这里的3是指数据库已经发展到第3个版本了。

 

            > 数据库存储数据

                优点:相比上面几种方式,效率更高。里面封装了各种查询,插入,删除,更新数据等算法,速度非常快。

 

                缺点:它是关系型数据库,不是对象型数据库。对象型数据库可以直接将一个对象存储到数据库中。关系型数据库则需要将对象进行解码,然后编写 sql语句来保存数据,比较蛋疼。

                数据库一般是用来存储数据量比较大的项目中。

 

        * Core Data

            > 是苹果官方提供给开发者专门做数据持久化的框架。它是对SQLite3的封装,使用它不需要编写任何SQL语句就能够将OC对象转化成数据,保存在SQLite3数据库文件中,也能够将保存在数据库中的数据还原成OC对象。

 

二、数据存储在哪里?

        每个应用的沙盒目录都是相似的,主要包含下面4个目录:

        1> 应用名称.app

            ① 存放内容:该目录包含了应用程序本身的数据,包括资源文件和可执行文件等。程序启动以后,会根据需要从该目录中动态加载代码或资源到内存,这里用到了lazy loading的思想。

            ② 整个目录是只读的 为了防止被篡改,应用在安装的时候会将该目录签名。非越狱情况下,该目录中内容是无法更改的;在越狱设备上如果更改了目录内容,对应的签名就会被改变,这种情况下苹果官网描述的后果是应用程序将无法启动。

            ③是否会被iTunes同步:否

 

       2> Documents文件夹

            ① 存放内容:我们可以将应用程序的数据文件保存在该目录下。不过这些数据类型仅限于不可再生的数据。可再生的数据文件应该存放在Library/Cache目录下。

            ② 是否会被iTunes同步:是

 

       3> Library文件夹

        3.1 > Library/Caches

            ① 存放内容:主要是缓存文件,用户使用过程中缓存都可以保存在这个目录中。那么这个目录就用于保存那些可再生的文件,比如网络请求的数据。鉴于此,应用程序通常还需要负责删除这些文件。

            ② 是否会被iTunes同步:否。

 

        3.2 > Library/Preferences

            ① 存放内容:应用程序的偏好设置文件。我们使用NSUserDefaults写的设置数据都会保存到该目录下的一个plist文件中.

            ② 是否会被iTunes同步:是

 

       4> tmp文件夹

            ① 存放内容:各种临时文件,保存应用再次启动时不需要的文件。而且,当应用不再需要这些文件时应该主动将其删除,因为该目录下的东西随时有可能被系统清理掉,目前已知的一种可能清理的原因是系统磁盘存储空间不足的时候。

            ② 是否会被iTunes同步:否

 

三、演示存储数据

    1)、plist文件存储数据

        //获取路径方式一

        // 1.获得沙盒根路径

        NSString *homePath = NSHomeDirectory();

        // 2.doucment 路径 (不建议采用,因为新版本的操作系统可能会修改目录名)

        NSString *docPath = [homePath stringByAppendingPathComponent:@"Documents"];

        // 3.plist 路径

        NSString *filePath = [docPath stringByAppendingPathComponent:@"data.plist"];

 

        //获取路径方式二 (推荐使用)

        // NSUserDomainMask 代表从用户文件夹下找

        // YES 代表展开路径中的波浪字符“~”

        NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, NO);

        // 在iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素

        NSString *docPath = [array objectAtIndex:0];

        // plist 路径

        NSString *filePath = [docPath stringByAppendingPathComponent:@"data.plist"];

 

        // 4.存储数据

        NSArray *data = @[@"guangzhouios",@100,@"cz"];

        [data writeToFile:filePath atomically:YES];

 

        注意:

        plist只能存储系统自带的一些常规的类, 也就是有writeToFile方法的对象才可以使用plist保存数据。字符串/字典/数组/NSNumber/NSData ...

        自定义的对象不能直接保存到plist中

 

    2)、偏好设置存储

        * 存储数据

            //1.获取NSUserDefaults对象

            NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];

 

            //2.保存数据

            [defaults setObject:@"pkxing" forKey:@"name"];

            [defaults setInteger:23 forKey:@"age"];

            [defaults setDouble:1.73f forKey:@"height"];

            [defaults setObject:@"man" forKey:@"gender"];

 

            //3.强制让数据立刻保存

            [defaults synchronize];

 

        * 读取数据

            //1.获取NSUserDefaults对象

            NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];

 

            //2.读取数据

            NSString *name = [defaults objectForKey:@"name"];

            NSInteger age = [defaults integerForKey:@"age"];

            double height = [defaults doubleForKey:@"height"];

            BOOL autoLogin = [defaults boolForKey:@"autoLogin"];

 

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

 

        好处:不需要关心文件夹名和文件名。它本质其实就是 plist 存储。

 

四、NSKeyedArchiver归档

1、如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复

不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以。

 

2、不使用 NSKeyedArchiver归档自定义对象

    步骤如下:

     1)、调用对象的dictionaryWithValuesForKeys:方法,将对象中的属性名以字符串的方式装到数组中去作为方法参数,就能将对象转换成字典。然后调用字典的 writeToFile:atomically:方法就能存储到文件中。

         CZPerson *person = [[CZPerson alloc] init];

         person.name = @"pkxing";

         person.age = 28;

         person.height = 1.70;

         

         NSString *filePath = @"/Users/pkxing/Desktop/data.archieve";

         NSDictionary *dict = [person dictionaryWithValuesForKeys:@[@"name",@"age",@"height"]];

         [dict writeToFile:filePath atomically:YES];

     

     2)、从文件读取

         // 获得路径

         NSString *filePath = @"/Users/pkxing/Desktop/data.archieve";

         NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];

         // 创建对象

         CZPerson *person2 = [[CZPerson alloc] init];

         // kvc给模型属性赋值

        [person2 setValuesForKeysWithDictionary:dict];

 

3、使用 NSKeyedArchiver归档自定义的对象。

    步骤如下:

    1)、自定义一个类,并遵循 NSCoding协议。

    2)、实现 NSCoding协议的两个方法

        /**

         *  将对象归档的时候系统会自动调用(将对象写入文件之前会调用)。

         *  在这个方法中说清楚:

         *  > 哪些属性需要存储

         *  > 怎样存储这些属性

         */

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

            [encoder encodeObject:_name forKey:@"name"];

            [encoder encodeInt:_age forKey:@"age"];

            [encoder encodeDouble:_height forKey:@"height"];

        }

 

        /**

         *  当从文件中解档对象的时候,系统会自定调用。

         *  在这个方法中说清楚:

         *  > 哪些属性需要读取

         *  > 怎样读取这些属性

         */

        - (id)initWithCoder:(NSCoder *)decoder {

            self = [super init];

            if (self) {

                _name = [decoder decodeObjectForKey:@"name"];

                _age = [decoder decodeIntForKey:@"age"];

                _height = [decoder decodeDoubleForKey:@"height"];

            }

            return self;

        }

    3、使用 NSKeyedArchiver类保存对象到文件

        CZPerson *person = [[CZPerson alloc] init];

        person.name = @"pkxing";

        person.age = 28;

        person.height = 1.70;

 

        // 获得路径

        NSString *filePath = @"/Users/pkxing/Desktop/data.archieve";

        // 归档对象

        [NSKeyedArchiver archiveRootObject:person toFile:filePath];

 

    4、使用 NSKeyedUnarchiver 解档对象

        // 获得路径

        NSString *filePath = @"/Users/pkxing/Desktop/data.archieve";

        CZPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

        NSLog(@"person = %@",person.name);

 

    5、自定义 CZStudent 类继承 CZPerson。添加一个学号属性。

      注意点:

        1> 使用NSKeyedArchiver归档学生对象时候,想要将学号也进行保存的话,则CZStudent也要重写

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

                // 一定要调用父类的该方法,确保父类的属性也能被归档

                //为什么 CZPerson不用调?因为CZPerson的父类是 NSObject,没有该方法。

                [super encodeWithCoder:encoder];

                [encoder encodeObject:_no forKey:@"no"];

            }

 

            - (id)initWithCoder:(NSCoder *)decoder {

                if (self=[super initWithCoder:decoder]) { // 这里不能调用 init。因为CZStudent的父类不是 NSObject

                    _name = [decoder decodeObjectForKey:@"no"];

                }

                return self;

            }

posted @ 2015-07-04 00:57  子涛  阅读(116)  评论(0编辑  收藏  举报