一.iOS应用数据存储的常用方式:
1.XML属性列表( plist)
2.Preference (偏好设置)
3.NSKeydArchiver(归档)
4.SQLite3
5.Core Data
二.数据存储路径
1.Documents
NSDocumentDirectory
保存应用运行时
生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如:游戏应用可将游戏存档保存在该目录
注意:上架的时候不可以存放网络上的大数据,只能存放程序运行时产生的数据
2.tmp 临时文件
保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录
3.Library/Caches NSCachesDirectory
保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据
4.Library/Preference
保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
三.实现代码
- Plist存储
- plist不能存自定义的对象
- 一般都是存取字典和数组
- 下面方法建议使用第二种
存数据
- (IBAction)save:(id)sender {
//获取沙盒的根目录,有两种方式
------------------第一种方法-----------------------
//拼接`Documents`字符串
//NSString *homeDir = NSHomeDirectory();
//NSString *path = [homeDir stringByAppendingString:@"/Documents"];
//下面这方法会自动加上/
//NSString *path = [homeDir stringByAppendingPathComponent:@"Documents"];
--------------------第二种方法------------------------
//NSSearchPathForDirectoriesInDomains:返回值是一个数组NSArray,所以取出
//(在iOS开发中一定要展开因为不展开全路径的话是~,手机是不识别的,只有电脑才会识别)
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)[0];
NSString *filePathName = [path stringByAppendingPathComponent:@"data.plist"];
NSDictionary *dict = @{@"name" : @"小羊快跑",@"age" : @18};
[dict writeToFile:filePathName atomically:YES];
}
取数据
- (IBAction)read:(id)sender {
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *filePathName = [path stringByAppendingPathComponent:@"data.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePathName];
NSLog(@"%@",dict);
}
- Preference存储
- 需要用到NSUserDefaults这个类
- NSUserDefaults也是不能够存自定义的对象
- 使用NSUserDefaults,是不需要指定文件名
- 注意:NSUserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入
//存数据
- (IBAction)save:(id)sender {
//偏好设置
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"小羊快跑" forKey:@"name"];
[defaults setBool:YES forKey:@"isChoose"];
[defaults setInteger:18 forKey:@"age"];
//立即写入到文件
[defaults synchronize];
}
//取数据
- (IBAction)read:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:@"name"];
BOOL isChoose = [defaults boolForKey:@"isChoose"];
NSInteger age = [defaults integerForKey:@"age"];
NSLog(@"%@----%d---%ld",name,isChoose,age);
}
- 归档
- archiveRootObject执行这个方法时, 底层会调用要存的对象的encodeWithCoder方法,
- 调用encodeWithCoder目的就是想询问下要存对象的哪些属性.怎么存.
- 解档
- unarchiveObjectWithFile执行这个方法时,底层会调用要存的对象的initWithCoder方法,
- 调用initWithCoder目的就是想询问下要取对象的哪些属性.
- 不是所有的对象都可以直接用这种方法进行归档,只有遵守了
NSCoding
协议的对象才可以
//归档
- (IBAction)save:(id)sender {
//获取沙盒的路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *filePathName = [path stringByAppendingPathComponent:@"student.data"];
Person *per = [[Person alloc] init];
per.name = @"小羊快跑";
per.age = 18;
[NSKeyedArchiver archiveRootObject:per toFile:filePathName];
}
//解档
- (IBAction)read:(id)sender {
//获取沙盒的路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *filePathName = [path stringByAppendingPathComponent:@"student.data"];
Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:filePathName];
NSLog(@"name = %@",per.name); //输出"小羊快跑"
NSLog(@"age = %d",per.age); //输出"18"
}
Person.m文件实现如下
@implementation Person
//必须得要遵守NSCoding协议才行
-(void)encodeWithCoder:(NSCoder *)encoder{
NSLog(@"%s",__func__);
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeInt:self.age forKey:@"age"];
}
//当解析一个文件时就会调用.
-(instancetype)initWithCoder:(NSCoder *)decoder{
NSLog(@"%s",__func__);
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:@"name"];
self.age = [decoder decodeIntForKey:@"age"];
}
return self;
}
@end
SQLite3
,Core Data
后续补上