iOS之数据本地持久化
前言
-
每个iOS应用软件都有一个单独的文件目录,这个目录我们称之为沙盒。可以通过
NSHomeDirectory()
来获取当前应用软件的根目录。 -
沙盒目录(此处来源简书,参考作者ParadiseKiss)https://www.jianshu.com/p/a620b8ae7ab7
-
Documents:
保存用户产生的数据,iTunes同步设备的时候会备份该目录。用户产生的数据就是指用户在使用当前app的时候保存的一些数据,比如保存app中的图片、保存下载的文件等。 -
Library:
这个目录下有2个文件夹,一个是Caches
、一个是Preferences
,Caches主要保存缓存数据,比如SDWebImage
把缓存的图片就存放到该目录下。当程序退出后,改目录保存的文件一直存在。Preferences
在Xcode6之前保存的是偏好设置,比如NSUserDefaults
保存的文件。但是Xcode6
以上就保存到/Users/用户名/Library/ Developer/CoreSimulator/Devices/模拟器UDID/data/Library/Preferences/
文件夹下。
-
-
tmp:保存程序中的临时数据,当程序退出后系统会自动删除tmp中所有的文件。
// 获取Documents路径
NSString*docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) firstObject];
//获取Library的路径
NSString*libDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES) lastObject];
// 获取cache路径
NSString*cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES) firstObject];
// 获取tmp路径
NSString*tmpDir =NSTemporaryDirectory();
本地数据五种持久化方式
- NSUserDefaults (偏好设置)
- plist文件(属性列表)
- NSKeyedArchiver(归档)
- SQLite
- CoreData
1. NSUserDefaults
- NSUserDefaults是object-c语言中的一个单例对象,常用来储存用户相关信息。会存放在目录 Library/Preference下。
- NSUserDefaults只能存储
NSArray
,NSDictionary
,NSData
,NSString
,NSNumber
,NSDate
类型。 - 用法
//创建
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//NSUserDefaults中有不同类型的存储方式,可以选择对应的方法。
[defaults setObject:@"李四" forKey:@"name"];
[defaults setInteger:18 forKey:@"age"];
UIImage *headImg = [UIImage imageNamed:@"img"];
NSData *data = UIImageJPEGRepresentation(headImg,100);
[defaults setObject:data forKey:@"headImg"];
//(强制存储)数据同步到文件里,防止意外退出没有存储上
[defaults synchronize];
//读取
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSString *name = [def objectForKey:@"name"];
NSInteger age = [def integerForKey:@"age"];
//删除
[def removeObjectForKey:@"headImg"];
- 打开沙盒其实会发现在
Library/Preferences
目录下会生成一个plist文件。NSUserDefaults存储的信息会存储在里面。
2.plist
-
plist存储就是件一个plist文件来存储数据,存储字典与数组。可以用为纯代码创建,还可以用Xcode创建。
- 代码创建
/*** 写入 ***/
//获取沙盒文件目录
NSString *path= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
//拼接路径,这一步,沙盒中并不会存在`123.plist`文件
NSString *fileName = [path stringByAppendingPathComponent:@ "123.plist" ];
NSDictionary*dict =@{@"age":@18,@"name":@"李四"};
//写入后,再次打开沙盒会发现有了`123.plist`文件
[dict writeToFile:fileName atomically:YES];
/*** 读取 ***/
//获取`plist`路径
NSFileManager * defaultManager = [NSFileManager defaultManager];
NSURL * documentPath = [[defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]firstObject];
NSString * fileSavePath = [documentPath.path stringByAppendingPathComponent:@"123.plist"];
//存的是字典用字典读取,存的是数组用数组读取
NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:fileSavePath];
-
XCode创建,这样创建会存在软件包里,沙盒下并没有
1.New File
1.png
2.Property List
2.png
3.写入
3.png4.读取
//获取路径 NSString *plistPath = [[NSBundle mainBundle]pathForResource:@"propretyText" ofType:@"plist"]; NSMutableDictionary *dataDic = [[NSMutableDictionary alloc]initWithContentsOfFile:plistPath];
3.NSKeyedArchiver(归档)
-
NSKeyedArchiver
默认只能对NSDate
,NSNumber
,NSString
,NSArray
,NSDictionary
来进行归档。如果相对对象进行归档需要满足NSCoding
协议。
@interface Person : NSObject<NSCoding>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *age;
@property (nonatomic, copy) NSString *sex;
@end
@implementation Person
- (void)encodeWithCoder:(NSCoder *)aCoder
{
//强调 如果是子类,继承了其他类,父类也要遵循协议执行下面代码
//[super encodeWithCode:encode]
//编码
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.age forKey:@"age"];
[aCoder encodeObject:self.sex forKey:@"sex"];
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
//强调 如果是子类,继承了其他类,父类也要遵循协议执行下面代码
//self = [super initWithCoder:decoder]
//解码
if (self = [super init])
{
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeObjectForKey:@"age"];
self.sex = [aDecoder decodeObjectForKey:@"sex"];
}
return self;
}
@end
- 使用
Person *p = [[Person alloc] init];
p.name = @"王三口";
p.age = @"12";
p.sex = @"男";
//写入
NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
[NSKeyedArchiver archiveRootObject:p toFile:file];
//读取
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
-
结果
11.png
4.SQLite3
FMDB一个很好的管理SQLite
的第三方库。FMDB使用可以参考 https://www.jianshu.com/p/54e74ce87404
-
用sqlite3首选需要导入到项目中
22.png
*代码
//打开路径
NSString *fileName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"text.sqlite"];
//创建(打开)数据库 (如果数据库不存在,会自动创建)
int result = sqlite3_open(fileName.UTF8String, &_db);
//表示打开数据库成功
if (result == SQLITE_OK) {
const char *sql = "create table if not exists person (sex text, name text, age integer);";
char *error = NULL;//错误信息
// sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。
int tableResult = sqlite3_exec(_db, sql, NULL, NULL, &error);
//sqlite3_prepare_v2检测SQL语句的合法性,用于查询
// sqlite3_stmt *stmt = NULL;//定义一个stmt存放结果集
// int tableResult = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
//增删改查都需要判断
if (tableResult == SQLITE_OK) {
NSLog(@"成功表创建");
}else {
NSLog(@"创建失败:%s",error);
}
}
5.CoreData
-
CoreData
提供了一种“对象-关系映射”的功能,能将OC对象转化成数据,保存Sqlite中。能够合理管理内存,避免sql语句的麻烦。-
1.新建项目勾选 use core data
33.png -
2.创建表
55.png -
3.创建属性
66.png -
4.创建关联的实体对象
77.png
-
- 作者君懒,且不经常用到,详细代码使用可以参考https://www.jianshu.com/p/113047a478c5,