NSUserDefault
简单数据快速读写Property list
(属性列表)文件存储Archiver
(归档)SQLite
本地数据库CoreData
在移动端的数据持有化方式总体有两类:
内存指当前程序的运行空间,缓存速度快容量小,是临时存储文件用的,供CPU直接读写。打开一个程序,他是在内存中存储,关闭程序后内存就又回到原来的空间空间。
磁盘是程序的存储空间,缓存容量大、速度慢、可持有化。与内存不同的是磁盘是永久存储东西的。
每个iOS应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用的文件系统隔离, iOS系统不允许访问其他应用的应用沙盒。在iOS8中已经开放访问(extension)。extension是iOS8新开放的一种对几个固定系统区域的扩展机制,它可以在一定程度上弥补iOS的 沙盒机制对应用间通信的限制。
应用沙盒一般包括以下几个文件目录:应用程序包、Documents、Libaray(下面有Caches和 Preferences目录)、tmp。
应用程序包
:包含所有的资源文件和可执行文件。Documents
:保存应用运行时生成的需要持久化的数据,iTunes
会自动备份该目录。苹果建议将程 序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes
备份和恢复的时候会包括此目 录tmp
:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行 时,系统也有可能会清除该目录下的文件,iTunes
不会同步该目录。iphone重启时,该目录下的 文件会丢失。Library
:存储程序的默认设置和其他状态信息,iTunes
会自动备份该目录。Libaray/Caches
:存放缓存文件,iTunes
不会备份此目录,此目录下文件不会在应用退出删除。一 般存放体积比较大,不是特别重要的资源。Libaray/Preferences
:保存应用的所有偏好设置,iOS的Settings
(设置)应用会在该目录中查找 应用的设置信息,iTunes
会自动备份该目录。// 获取沙盒根目录路径
NSString *path = NSHomeDirectory();
注意: 每次编译代码会生成新的沙盒路径,注意是编译不是启动,所以模拟机或者真机运行,每次运行所得到的沙盒路径都是不一样的,线上版本app真机不会生成新的沙盒路径。
上面的代码得到的就是当前应用程序目录的路径,该目录下就是应用程序的沙盒,在该目录下有4个文件夹:Documents
、Library
、SystemData
、tmp
,当前应用程序只能访问该目录下的文件。
//获取沙盒根路径
NSString *path = NSHomeDirectory();
NSLog(@"沙盒根路径:%@", path);
//Document路径
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSLog(@"Document目录路径:%@", docDir);
// 获取Library的目录路径
NSString *libDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"Libarary目录路径:%@", libDir);
// 获取Caches目录路径
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSLog(@"Cacheas目录路径:%@", cachesDir);
// library Preference
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(@"偏好设置目录路径:%@", defaults);
// 获取tmp目录路径
NSString *tmpDir = NSTemporaryDirectory();
NSLog(@"tmp目录路径:%@", tmpDir);
属性列表是一种XML格式的文件,拓展名为plist
。
如果对象是NSString
、NSDictionary
、NSArray
、NSData
、NSNumber
等类型,就可以使用
writeToFile:atomically:
方法直接将对象写到属性列表文件中,举例说明:
// 获取 Document 文件目录
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
// 在 Document 目录下新建一个 test.plist 文件
NSString * filePath = [docPath stringByAppendingPathComponent:@"test.plist"];
// 存字典,将字典数据存到刚才的 test.plist 文件
NSDictionary* dict = @{ @"name" :@"zxb10", @"age" : @"20" };
[dict writeToFile:filePath atomically:YES];
// 取字典,从刚才的 test.plist 文件中取出字典数据
NSDictionary* dictA = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"%@", dictA);
// 存数组
NSArray* array = @[@"zxb10", @"20"];
[array writeToFile:filePath atomically:YES];
// 取数组
NSArray* arrayA = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@", arrayA);
输出结果:
我们可以在document目录下找到这个文件:
因为我们最后是存储的 NSArray 数据类型的,所以他这里也就是 NSArray 类型的数据。
很多iOS应用都支持偏好设置,提供了一套标准的解决方案来为应用加入偏好设置功能,比如保存用户名,字体大小,密码,是否自动登录等。
每个应用都有个NSUserDefaults
实例,可以通过它来存取偏好设置,不需要路径。其本身的创建类似于单例模式,我们在后面用不同的属性名再次申请创建,会覆盖之前的数据。
NSUserDefaults
:简单数据快速读写,不能存储自定义类型。
UserDefaults
设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set
方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize
方法[defaults synchornize];
强制写入。
偏好设置存储的优点:
我们使用UserDefaults
注册一个账号密码试一下:
// 获取偏好设置对象
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//存储数据
[defaults setObject:@"zxb10" forKey:@"name"];
[defaults setObject:@"zxbnb666" forKey:@"password"];
// 同步调用,立刻写到文件中,不写这个方法会异步,有延迟
[defaults synchronize];
// 需要验证账号密码的地方,获取偏好设置对象
NSUserDefaults *defaultsA = [NSUserDefaults standardUserDefaults];
NSString *name = [defaultsA objectForKey:@"name"];
NSString *password = [defaultsA objectForKey:@"password"];
NSLog(@"name:%@ password:%@", name, password);
SQLite:
CoreData:
FMDB:
SQLite
和CoreData
的区别:
CoreData
可以在一个对象更新时,其关联的对象也会随着更新,相当于你更新一张表时,其关联的其他表的也会随着更新。CoreData
供更简单的性能管理机制,可以限制查询记录的总数,这个类会自动更新其缓存。CoreData
没有SQL直观,没有类似外连接,左连接等操作。// 其中,Show为我们plist文件的名称,后面的plist是Show的扩展名
// 写入plist
- (void)setDataFromPlist {
NSString *plist = [[NSBundle mainBundle] pathForResource:@"Show" ofType:@"plist"];
NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
[temp setValue:@20 forKey:@"age"];
[temp setValue:@"男" forKey:@"sex"];
[temp writeToFile:plist atomically:YES];
}
// 读取plist
- (void)getDataFromPlist {
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Show" ofType:@"plist"];
NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
NSLog(@"%@", dataDic);//直接打印数据
}