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

    iOS中的数据存储(上)

    iOS应用数据存储的常用方式:

        1> XML属性列表(plist)归档.

        2> Preference(偏好设置).

        3> NSKeyedArchiver归档.

        4> SQLite3

        5> Core Data

    应用沙盒:

        每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录)与其他文件系统隔离.应用必须待在自己的沙盒里,其他应用不能访问该沙盒.

        模拟器应用沙盒的根路径在: (apple是用户名, 6.0是模拟器版本)

        /Users/apple/Library/Application Support/iPhone Simulator/6.0/Applications

    或者: /Users/用户名/资源库/Application Support/iPhone Simulator/6.1/Applications

    注意:

        默认情况下,模拟器的目录是隐藏的,要想显示出来,需要在Mac终端输入下面的命令:

        显示Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles YES

        隐藏Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles NO

    应用沙盒结构分析

    Documents:

        保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录.例如游戏应用可将游戏存档保存在该目录.

    temp:

        保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除.应用没有运行时,系统也可能会清除该目录下的文件.iTunes同步设备时不会备份该目录.

    Library/Caches:

        保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录.一般存储体积大,不需要备份的非重要数据.

    Library/Preference:

        保存应用的所有偏好设置,iOS的setting(设置)应用会在该目录中查找应用的设置信息.iTunes同步设备时会备份该目录.

    应用沙盒目录的常见获取方式:

    沙盒根路径:

    1
    NSString *home = NSHomeDirectory();

    Documents:(2种方式)

        1> 利用沙盒根目录拼接"Documents"字符串:

    1
    2
    3
    NSString *home = NSHomeDirectory();
    NSString *documents = [home stringByAppendingPathComponent:@"Documents"];
    // 不建议采用,因为新版本的操作系统可能会修改目录名

        2> 利用NSSearchPathForDirectoriesInDomains函数:

    1
    2
    3
    4
    5
    // NSUserDomainMask 代表从用户文件夹下找
    // YES 代表展开路径中的波浪字符“~”
    NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, NO);
    // 在iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素
    NSString *documents = [array objectAtIndex:0];

    tmp: 

    1
    NSString *tmp= NSTemporaryDirectory();

    Library/Catches:(跟Documents类似的两种方法)

        1> 利用沙盒跟目录拼接"Catches"字符串.

        2> 利用NSSearchPathForDirectoriesInDomains函数(将函数的第一个参数改为:NSCachesDirectory即可).

    Library/Preference:通过NSUserDefaults类存取该目录下的设置信息.

        下面分别详细介绍5中数据存数方式.

    属性列表

        属性列表是一种XML格式的文件,拓展名为plist.

        如果对象是NSString, NSDictionary, NSArray, NSData, NSNumber等类型,就可以使用:writeToFile:atomiclly:方法直接将对象写到属性列表文件中.

    属性列表-归档NSDictionary

        将一个NSDictionary归档到一个plist属性列表中.

    1
    2
    3
    4
    5
    6
    // 将数据封装成字典
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:@"15013141314" forKey:@"phone"];
    [dict setObject:@"27" forKey:@"age"];
    // 将字典持久化到Documents/stu.plist文件中
    [dict writeToFile:path atomically:YES];

    属性列表-恢复NSDictionary

        读取属性列表,恢复NSDictionary对象

    1
    2
    3
    4
    // 读取Documents/stu.plist的内容,实例化NSDictionary
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
    NSLog(@"phone:%@", [dict objectForKey:@"phone"]);
    NSLog(@"age:%@", [dict objectForKey:@"age"]);

    偏好设置(Preference)

        很多iOS应用都支持偏好设置,比如保存用户名,密码,是否自动登录等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能.

        每个应用都有个NSUserDefaults实例,通过它来存取偏好设置.

        如保存用户名,字体大小,是否登录

    1
    2
    3
    4
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:@"JN521" forKey:@"username"];
    [defaults setFloat:18.0f forKey:@"text_size"];
    [defaults setBool:YES forKey:@"auto_login"];

        读取上次保存的设置

    1
    2
    3
    4
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *username = [defaults stringForKey:@"username"];
    float textSize = [defaults floatForKey:@"text_size"];
    BOOL autoLogin = [defaults boolForKey:@"auto_login"];

    注意:

        UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘.所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了.出现此问题,可以通过调用synchornize方法强制写入.

    1
    [defaults synchornize];

    NSKeyedArchiver

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

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

    NSCoding协议有2个方法:

    encodeWithCoder:

        每次归档对象时,都会调用这个方法.一般在这个方法里面指定如何归档对象中的每个实例变量.可以使用:encodeObject:forkey:方法归档实例变量.

    initWithCoder:

        每次从文件中恢复(解码)对象时,都会调用这个方法.一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forkey方法解码实例变量.

        归档一个NSArray对象到Documents/array.archive :

    1
    2
    3
    NSString *path = [NSString stringWithFormat:@"Documents/array.archive"];
    NSArray *array = [NSArray arrayWithObjects:@"a",@"b",nil];
    [NSKeyedArchiver archiveRootObject:array toFile:path];

        恢复(解码)NSArray对象

    1
    NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

    NSKeyedArchiver-归档Person对象:

    Person.h中:

    1
    2
    3
    4
    5
    @interface Person : NSObject <NSCoding>
    @property(nonatomic,copy) NSString *name;
    @property(nonatomic,assign) int age;
    @property(nonatomic,assign) float height;
    @end

    Person.m中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    @implementation Person
    -(void)encodeWithCoder:(NSCoder*)encoder
    {
        [encoder encodeObject:self.name forKey:@"name"];
        [encoder encodeInt:self.age forKey:@"age"];
        [encoder encodeFloat:self.height forKey:@"height"];
    }
    -(id)initWithCoder:(NSCoder*)decoder 
    {
        self.name= [decoder decodeObjectForKey:@"name"];
        self.age= [decoder decodeIntForKey:@"age"];
        self.height= [decoder decodeFloatForKey:@"height"];
        return self;
    }
     
    // 归档(编码)
    Person *person = [[Person alloc] init];
    person.name = @"JN";
    person.age = 22;
    person.height = 1.63f;
    [NSKeyedArchiver archiveRootObject:person toFile:path];
    // 恢复(解码)
    Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
     
    @end

    NSKeyedArchiver-归档对象的注意

    如果父类也遵守了NSCoding协议,请注意:

        1> 应该在uencodeWithCoder:方法中加上一句 [super encodeWithCode:encode];确保继承的实例变量也能被编码,即也能被归档.

        2> 应该在initWithCoder:方法中加上一句 self = [super initWithCoder:decoder];确保继承的实例变量也能被解码,即也能被恢复.

    NSData

        使用archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象.

        NSData可以为一些数据提供临时的存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容.可以使用[NSMutableData data]创建可变数据空间.

    NSData归档2个Person对象到同一文件中:

        归档:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 新建一块可变数据区
    NSMutableData *data = [NSMutableData data];
    // 将数据区连接到一个NSKeyedArchiver对象
    NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
    // 开始存档对象,存档的数据都会存储到NSMutableData中
    [archiver encodeObject:person1 forKey:@"person1"];
    [archiver encodeObject:person2 forKey:@"person2"];
    // 存档完毕(一定要调用这个方法)
    [archiver finishEncoding];
    // 将存档的数据写入文件
    [data writeToFile:path atomically:YES];

        恢复(解码):

    1
    2
    3
    4
    5
    6
    7
    8
    // 从文件中读取数据
    NSData *data = [NSData dataWithContentsOfFile:path];
    // 根据数据,解析成一个NSKeyedUnarchiver对象
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
    Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
    // 恢复完毕
    [unarchiver finishDecoding];

    利用归档实现深复制:比如对一个Person对象进行深复制

    1
    2
    3
    4
    5
    6
    7
    8
    // 临时存储person1的数据
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
    // 解析data,生成一个新的Person对象
    Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
     
    // 分别打印内存地址
    NSLog(@"person1:%@", person1); // person1:0x8d3ed10>
    NSLog(@"person2:%@", person2); // person2:0x8d3e2f0>
  • 相关阅读:
    Interview with BOA
    Java Main Differences between HashMap HashTable and ConcurrentHashMap
    Java Main Differences between Java and C++
    LeetCode 33. Search in Rotated Sorted Array
    LeetCode 154. Find Minimum in Rotated Sorted Array II
    LeetCode 153. Find Minimum in Rotated Sorted Array
    LeetCode 75. Sort Colors
    LeetCode 31. Next Permutation
    LeetCode 60. Permutation Sequence
    LeetCode 216. Combination Sum III
  • 原文地址:https://www.cnblogs.com/Jenaral/p/5279784.html
Copyright © 2011-2022 走看看