在iOS开发过程中,不管是做什么应用,都会碰到数据存储的问题。将数据存储到本地,能够让程序的运行更加流畅,不会出现让人厌烦的菊花,使得用户体验更好。下面介绍一下数据保存的方式:
1.Write写入方式:永久保存在磁盘中。具体方法为:
第一步:获得文件即将保存的路径:
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);//使用C函数NSSearchPathForDirectoriesInDomains来获得沙盒中目录的全路径。该函数有三个参数,其中布尔值表示是否需要通过~扩展路径。
还有一种方法是使用NSHomeDirectory函数获得sandbox的路径:
NSHomeDirectory();// Once you have the full sandbox path, you can create a path from it,但是不能在sandbox的本文件层上写文件也不能创建目录,而应该是此基础上创建一个新的可写的目录,例如Documents,Library或者temp。NSString *documentPath = [sandboxPath stringByAppendingPathComponent:@"Documents"];//将Documents添加到sandbox路径上,具体原因前面分析了!
这两者的区别就是:使用NSSearchPathForDirectoriesInDomains比在NSHomeDirectory后面添加Document更加安全。因为该文件目录可能在未来发送的系统上发生改变。
第二步:生成在该路径下的文件:
[documentDirectory stringByAppendingPathComponent:fileName];//fileName就是保存文件的文件名
第三步:往文件中写入数据:
[data writeToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName
最后:从文件中读出数据:
[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//从FileName中读取出数据
2.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码
@interface Person:NSObject<NSCoding>{//遵守NSCoding协议
NSString *name;//待归档类型
}
@implementation Person
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:name forKey:@"name"];
}
-(void)initWithCoder:(NSCoder *)aDecoder{
name=[[aDeCoder decodeObjectforKey:@"name"] retain];**
}
归档操作:
对Person对象归档操作
//将复杂对象归档之后存入本地
//第一步:创建一个NSMutableData 用于初始化归档工具
NSMutableData *data = [NSMutableData data];
//第二步: 创建一个归档工具
NSKeyedArchiver *keyedArchiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//第三步:使用归档工具 对需要归档的对象进行归档
[keyedArchiver encodeObject:person forKey:@"person"];
//第四步: 结束归档
[keyedArchiver finishEncoding];
NSLog(@"data3 === %@",data);
NSString *filePath = [documentPathStr stringByAppendingPathComponent:@"person.plist"];
[data writeToFile:filePath atomically:YES];
NSLog(@"filePath == %@",filePath);
缺点:归档的形式来保存数据,只能一次性归档保存以及一次性解压。所以只能针对小量数据,而且对数据操作比较笨拙,即如果想改动数据的某一小部分,还是需要解压整个数据或者归档整个数据。归档数据储存到本地实际上还是采用直接写入本地的方式
3.NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。
具体实现为:
保存数据:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name = @”default string“;
[defaults setObject:firstName forKey:@"name"];
//获得UIImage实例
UIImage *image = [[UIImage alloc] initWithContentsOfFile:@"photo.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 100);//UIImage对象转换成NSData
[defaults synchronize];//用synchronize方法把数据持久化到standardUserDefaults[数据库]
读取数据:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:@"name"];//根据键值取出name
NSData *imageData = [defaults dataForKey:@"image"];
UIImage *Image = [UIImage imageWithData:imageData];//NSData转换为UIImage
4. SQLite:采用SQLite数据库来存储数据。
第一步:需要添加SQLite相关的库以及头文件:
在项目文件的Build Phases下,找到Link Binary With Libraries,添加libsqlite3.0.tbd;
PS:libsqlite3.0.tbd和libsqlite3.tbd的区别
使用过sqlite的同学都会发现在加载sqlite类库的时候会出现两个libsqlite3.0.dylib和libsqlite3.dylib,之前我一直以为它们是两个版本的,但是后来发现其实libsqlite3.0.dylib本身是一个连接,它指向libsqlite3.dylib,如图所示:
我相信这个图就能向大家说明一切,但是这里就有疑问了,直接引用libsqlite3.dylib不就行了,为什么要用libsqlite3.0.dylib,其实这个指针总是指向最新的sqlite3动态库,比如说sqlite3库更新了,如果我们引用的是libsqlite3.0.dylib你就不需要做任何修改了。
第二步:开始使用SQLite:
//1.打开数据库
//2.对数据库进行操作
//3.关闭数据库
5.使用CoreData存储数据
1.Core Data 是数据持久化存储的最佳方式
2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型
3.好处:能够合理管理内存,避免使用sql的麻烦,高效
4.构成:
(1)NSManagedObjectContext(被管理的数据上下文)
操作实际内容(操作持久层)
作用:插入数据,查询数据,删除数据
(2)NSManagedObjectModel(被管理的数据模型)
数据库所有表格或数据结构,包含各实体的定义信息
作用:添加实体的属性,建立属性之间的关系
操作方法:视图编辑器,或代码
(3)NSPersistentStoreCoordinator(持久化存储助理)
相当于数据库的连接器
作用:设置数据存储的名字,位置,存储方式,和存储时机
(4)NSManagedObject(被管理的数据记录)
相当于数据库中的表格记录
(5)NSFetchRequest(获取数据的请求)
相当于查询语句
(6)NSEntityDescription(实体结构)
相当于表格结构
(7)后缀为.xcdatamodeld的包
里面是.xcdatamodel文件,用数据模型编辑器编辑
编译后为.momd或.mom文件