iOS应用创建的数据存储方式
-
plist文件,是XML属性的列表形式
- ios 的偏好设置,就是基于plist文件
NSKeyedArchiver
归档(遵循NSCodeing
协议)SQLite(需要自己写sql语句)
Core Data 苹果对
SQLite
的一个封装
今天我们先来说说
plist
文件,需要知道一个概念
沙盒文件
每一个iOS应用都有自己的沙盒文件,与其他的文件系统隔离,应用须待在自己的沙盒文件里面,其他应用不能访问该应用的沙盒文件
--
- 如何看到应用的文件目录呢
NSHomeDirectory()
这个方法
从上图中我们可以看到的目录, 主要目录的路径,开头
Application
,之前我们在UIApplication
的时候有说过,UIApplication
就代表一个程序的象征,所以iOS应用开头的路径一般都是Application
关于目录文件的一些介绍
Documents
目录
Documents
保存应用运行时生成的需要持久化的数据
,一般是iTunes
同步设备时来使用备份的目录
-
tmp
目录
tmp
临时存储数据,就是当程序在次运行的时候,这些数据就会被系统删除
-
Library
这个一般是开发人员使用的
Library
里面存放了2个子目录Caches
和Preferences
Caches
运行程序时生成的需要持久化数据的文件目录,一般下载的视频或者文件会存储在这个目录,存储的体积大
Preferences
偏好设置文件目录,比如:账号 密码 等 会与iTunes
同步设备时备份
- 访问
Documents
目录
/*
第一个参数:要获取的目录
第二个参数:搜索的范围(NSUserDomainMask:在自己文件下搜索)
第三个参数:是否展开路径
*/
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- 访问
Caches
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
1- 保存数据
//获取路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
//拼接文件路径 plist文件
NSString *filePath =[path stringByAppendingPathComponent:@"data.plist"];
// NSLog(@"%@",filePath);
NSFileManager *manager = [NSFileManager defaultManager];
//判断文件或者文件夹是否存在
BOOL isYewOrNo = [manager fileExistsAtPath:filePath];
if (isYewOrNo) {
NSArray *datas = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@",datas);
}else{
//写入数据
NSArray *data = @[@(110)];
[data writeToFile:filePath atomically:YES];
}
2- 保存偏好设置的数据 这个数据就会保存在
Preferences
目录
//获取文件
NSUserDefaults *defaluts = [NSUserDefaults standardUserDefaults];
// 设置数据
[defaluts setObject:@"CC" forKey:@"name_key"];
[defaluts setObject:@"18" forKey:@"age_key"];
//同步设置数据
[defaluts synchronize];
归档NSKeyedArchiver
- 针对自定义的类进行数据存储
- 要进行归档的类,必须遵循
NSCoding
协议
CCPerson
类的.h
文件 遵循NSCoding
@interface CCPerson : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end
CCPerson
类的.m
文件 实现协议的方法
//解档
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name_key"];
self.age = [[aDecoder decodeObjectForKey:@"age_key"] intValue];
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name_key"];
[aCoder encodeObject:@(self.age) forKey:@"age_key"];
}
自定义类的数据存储
//归档
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
//拼接路径
NSString *filepath = [path stringByAppendingPathComponent:@"person.data"];
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filepath]) {
CCPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filepath];
NSLog(@"%@--%d",person.name,person.age);
}else {
//创建对象
CCPerson *person = [[CCPerson alloc] init];
person.name = @"小名";
person.age = 18;
BOOL isSuc = [NSKeyedArchiver archiveRootObject:person toFile:filepath];
NSLog(@"%@",(isSuc == YES ? @"成功":@"失败"));
}
注意:苹果为了提高数据的安全性在iOS11
推出了一个新的方法
+ (nullable NSData *)archivedDataWithRootObject:(id)object requiringSecureCoding:(BOOL)requiresSecureCoding error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0))
,来代替下面的归档的方法
- 这2个方法在
iOS11
之后弃用,iOS10
可以使用
+ (NSData *)archivedDataWithRootObject:(id)rootObject API_DEPRECATED("Use +archivedDataWithRootObject:requiringSecureCoding:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path API_DEPRECATED("Use +archivedDataWithRootObject:requiringSecureCoding:error: instead", macosx(10.2,10.14), ios(2.0,12.0), watchos(2.0,5.0), tvos(9.0,12.0));
如果使用
iOS11
或者以上的系统,那么自定义的类CCPerson
要遵循NSSecureCoding
协议
@interface CCPerson : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end
- 数据存储归档
iOS11
//需要注意是:第二个参数是yes的话必须遵循NSSecureCoding,如果是NO的话可以是NSCoding协议
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:&error];
NSLog(@"------%@",error.description);
BOOL isSuc =[data writeToFile:filepath atomically:YES];
NSLog(@"%@",(isSuc == YES ? @"成功":@"失败"));
保存路径的更改,上面再使用归档保存自定义类的数据时,我们一般创建一个
宏
来存储路径,方便我们使用,其实如果是账户类的数据保存
,直接存储到NSUserDefaults
可以
//创建对象
CCPerson *person = [[CCPerson alloc] init];
person.name = @"小名";
person.age = 18;
NSError *error = nil;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:&error];
//保存的路径
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:data forKey:@"data_key"];
//同步数据
defaults synchronize];