一.plist存储
条件:
● 属性列表是一种XML格式的文件,拓展名为plist
● 如果对象是NSString、NSDictionary、NSArray、NSData、 NSNumber等类型,就可以使用writeToFile:atomically:⽅法 直接将对象写到属性列表文件中
什么能做
plist
存储?
一定要有write to file的方法
2.搜索哪个文件夹
NSDocumentDirectory :
搜索哪个文件夹
3.在哪搜索
NSUserDomainMask :
在哪搜索
4.完整存的代码
- (
IBAction
)save:(
id
)sender
{
// 什么能做 plist 存储
// 一定要有 write to file 的方法
// 获取 doc 目录
// NSDocumentDirectory : 搜索哪个文件夹
// NSUserDomainMask : 在哪搜索
NSString * docPath = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES )[ 0 ];
// filePath
NSString * filePath = [docPath stringByAppendingPathComponent : @"xx.plist" ];
// // 创建一个字典
// NSDictionary* dict = @{ @"key" : @"value",
// @"key1" : @"value1" };
//
// // 存
// [dict writeToFile:filePath atomically:YES];
// 创建 array
NSArray * array = @[ @" 传智播客 " , @" 你好 " ] ;
// atomically: 线程安全的
[array writeToFile :filePath atomically : YES ];
}
{
// 什么能做 plist 存储
// 一定要有 write to file 的方法
// 获取 doc 目录
// NSDocumentDirectory : 搜索哪个文件夹
// NSUserDomainMask : 在哪搜索
NSString * docPath = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES )[ 0 ];
// filePath
NSString * filePath = [docPath stringByAppendingPathComponent : @"xx.plist" ];
// // 创建一个字典
// NSDictionary* dict = @{ @"key" : @"value",
// @"key1" : @"value1" };
//
// // 存
// [dict writeToFile:filePath atomically:YES];
// 创建 array
NSArray * array = @[ @" 传智播客 " , @" 你好 " ] ;
// atomically: 线程安全的
[array writeToFile :filePath atomically : YES ];
}
5.完整取的代码
// 取数据
- ( IBAction )read:( id )sender
{
// 获取 doc 目录
NSString * docPath = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES )[ 0 ];
// filePath
NSString * filePath = [docPath stringByAppendingPathComponent : @"xx.plist" ];
// NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
// NSLog(@"%@", dict);
NSArray * array = [ NSArray arrayWithContentsOfFile :filePath];
NSLog ( @"%@" , array);
- ( IBAction )read:( id )sender
{
// 获取 doc 目录
NSString * docPath = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES )[ 0 ];
// filePath
NSString * filePath = [docPath stringByAppendingPathComponent : @"xx.plist" ];
// NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
// NSLog(@"%@", dict);
NSArray * array = [ NSArray arrayWithContentsOfFile :filePath];
NSLog ( @"%@" , array);
}
二.偏好设置存储
条件:
1.
不需要关心文件名
2.
快速的做键值对的存储
3. NSUserDefaults
实际上就是系统对字典的封装
很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能
3.重要说明
(1)偏好设置是专门用来保存应用程序的配置信息的, 一般情况不要在偏好设置中保存其他数据。如果利用系统的偏好设置来存储数据, 默认就是存储在Preferences文件夹下面的,偏好设置会将所有的数据都保存到同一个文件中。
(2)使用偏好设置对数据进行保存之后, 它保存到系统的时间是不确定的,会在将来某一时间点自动将数据保存到Preferences文件夹下面,如果需要即刻将数据存储,可以使用[defaults synchronize];
(3)注意点:所有的信息都写在一个文件中,对比简单的plist可以保存和读取基本的数据类型
(4)步骤:获取NSuserDefaults,保存(读取
3.强制数据存储
//
同步
ios8
以后不需要调用也可以正常使用
[ud synchronize];
4.代码如下:
//
存数据
- ( IBAction )save:( id )sender
{
// 1. 不需要关心文件名
// 2. 快速的做键值对的存储
// 3. NSUserDefaults 实际上就是系统对字典的封装
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ];
[ud setObject : @"value" forKey : @"key" ];
[ud setBool : YES forKey : @"isOn" ];
// 同步 ios8 以后不需要调用也可以正常使用
[ud synchronize ];
}
- ( IBAction )save:( id )sender
{
// 1. 不需要关心文件名
// 2. 快速的做键值对的存储
// 3. NSUserDefaults 实际上就是系统对字典的封装
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ];
[ud setObject : @"value" forKey : @"key" ];
[ud setBool : YES forKey : @"isOn" ];
// 同步 ios8 以后不需要调用也可以正常使用
[ud synchronize ];
}
// 取数据
- ( IBAction )read:( id )sender
{
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ];
NSLog ( @"%@" , [ud objectForKey : @"key" ]);
}
- ( IBAction )read:( id )sender
{
NSUserDefaults * ud = [ NSUserDefaults standardUserDefaults ];
NSLog ( @"%@" , [ud objectForKey : @"key" ]);
}
三.归档和解挡
在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦;
偏好设置(将所有的东西都保存在同一个文件夹下面,且主要用于存储应用的设置信息)
归档:因为前两者都有一个致命的缺陷,只能存储常用的类型。归档可以实现把自定义的对象存放在文件中。
1.文件结构
三,代码如下:::::
1. 存数据
- (
IBAction
)save:(
id
)sender
{
// 获取文件路径
NSString * tmpPath = NSTemporaryDirectory ();
NSString * filePath = [tmpPath stringByAppendingPathComponent : @"teacher.data" ];
Teacher * t = [[ Teacher alloc ] init ];
t. name = @" 传智播客 " ;
t. age = 18 ;
// 自定义的对象保存到文件中
[ NSKeyedArchiver archiveRootObject :t toFile :filePath];
{
// 获取文件路径
NSString * tmpPath = NSTemporaryDirectory ();
NSString * filePath = [tmpPath stringByAppendingPathComponent : @"teacher.data" ];
Teacher * t = [[ Teacher alloc ] init ];
t. name = @" 传智播客 " ;
t. age = 18 ;
// 自定义的对象保存到文件中
[ NSKeyedArchiver archiveRootObject :t toFile :filePath];
}
2. 取数据
- (
IBAction
)read:(
id
)sender
{
// 获取文件路径
NSString * tmpPath = NSTemporaryDirectory ();
NSString * filePath = [tmpPath stringByAppendingPathComponent : @"teacher.data" ];
// 从文件中读取对象
Teacher * t = [ NSKeyedUnarchiver unarchiveObjectWithFile :filePath];
NSLog ( @"%d" , t. age );
{
// 获取文件路径
NSString * tmpPath = NSTemporaryDirectory ();
NSString * filePath = [tmpPath stringByAppendingPathComponent : @"teacher.data" ];
// 从文件中读取对象
Teacher * t = [ NSKeyedUnarchiver unarchiveObjectWithFile :filePath];
NSLog ( @"%d" , t. age );
}
3.自定义对象
//
当将一个自定义对象保存到文件的时候就会调用该方法
// 在该方法中说明如何存储自定义对象的属性
// 告诉系统需要归档哪些属性
- ( void )encodeWithCoder:( NSCoder *)aCoder
{
[aCoder encodeInt : _age forKey : @"age111111" ];
[aCoder encodeObject : _name forKey : @"name" ];
}
// 当从文件中读取一个对象的时候就会调用该方法
// 告诉系统解档哪些属性
- ( id )initWithCoder:( NSCoder *)aDecoder
{
// 注意 在构照方法中需要先初始化父类的方法
if ( self = [ super init ]) {
_age = [aDecoder decodeIntForKey : @"age111111" ];
_name = [aDecoder decodeObjectForKey : @"name" ];
}
return self ;
// 在该方法中说明如何存储自定义对象的属性
// 告诉系统需要归档哪些属性
- ( void )encodeWithCoder:( NSCoder *)aCoder
{
[aCoder encodeInt : _age forKey : @"age111111" ];
[aCoder encodeObject : _name forKey : @"name" ];
}
// 当从文件中读取一个对象的时候就会调用该方法
// 告诉系统解档哪些属性
- ( id )initWithCoder:( NSCoder *)aDecoder
{
// 注意 在构照方法中需要先初始化父类的方法
if ( self = [ super init ]) {
_age = [aDecoder decodeIntForKey : @"age111111" ];
_name = [aDecoder decodeObjectForKey : @"name" ];
}
return self ;
}
4.常见错误
关于不实现两个协议方法的错误提示:
-(void)encodeWithCoder:(NSCoder *)aCoder方法:
-(id)initWithCoder:(NSCoder *)aDecoder方法:
.遵守NSCoding协议,并实现该协议中的两个方法。
4.如果是继承,则子类一定要重写那两个方法。因为person的子类在存取的时候,会去子类中去找调用的方法,没找到那么它就去父类中找,所以最后保存和读取的时候新增加的属性会被忽略。需要先调用父类的方法,先初始化父类的,再初始化子类的。
5.保存数据的文件的后缀名可以随意命名。
6.通过plist保存的数据是直接显示的,不安全。通过归档方法保存的数据在文件中打开是乱码的,更安全。