============================= 演示数据的读、写。通过"plist文件"来存储 =============================
* 介绍"沙盒路径" 、 "Bundle 路径"
** /Users/...../Data/... 这个是沙盒路径
** /Users/...../Bundle/.... 这个是 Bundle 路径
* 介绍"沙盒"下的目录结构
1> Documents目录: 保存应用程序自己的数据(比如:游戏进度存档、软件的一些个人设置等)。通过 iTunes、iCloud 备份时, 会备份这个目录下的数据
2> Tmp 目录: 存储一些其他临时数据, 系统磁盘空间不够, 手机重启时, 会自动清除这个目录的数据。无需程序员手动清除该目录中的数据.iTunes、iCloud 备份时, 不会备份这个目录下的数据。
3> Caches 目录: 保存从网络上下载的文件(比如:听歌时的缓存、图片的缓存等),这个目录下的数据不会被自动删除,需要程序员自己实现清除目录数据功能。iTunes、iCloud 备份时, 不会备份这个目录下的数据。
4> Preference目录: 保存通过"偏好设置"写入的数据。iTunes、iCloud 备份时, 会备份这个目录下的数据。
* "沙盒" -> "Sandbox"
* "沙盒"示例路径: /Users/Steve/Library/Developer/CoreSimulator/Devices/0C63A035-071E-4EFC-8718-C387A3F7E026/data/Containers/Data/Application/287DAF0F-B201-4EDA-9E8A-D1DEDD9C9135
* 通过调用NSHomeDirectory();来获取沙盒的根目录。
NSString *sandboxPath = NSHomeDirectory();
* 获取"沙盒"下的"Documents"的路径
1> 方式一: 先获取"沙盒"根路径, 再获取Documents路径(拼接)。(不推荐, 因为一旦系统升级Documents目录名字变了就不能用了)
NSString *sandboxPath = NSHomeDirectory();
NSString *docPath = [sandboxPath stringByAppendingPathComponent:@"Documents"];
2> 方式二:
/** 参考代码:
// NSUserDomainMask 代表从用户文件夹下找, 沙盒根路径。
// YES 代表展开路径中的波浪字符“~”
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 在iOS中,只有一个目录跟传入的参数匹配(沙盒中只有一个Documents目录),所以这个集合里面只有一个元素
NSString *documents = [array objectAtIndex:0];
NSLog(@"%@", documents);
*/
* 向"沙盒"中写入数据
NSArray *array = @[@"Bob", @"John", @"Steve"];
NSString *filePath = [docPath stringByAppendingPathComponent:@"data.plist"];
[array writeToFile:filePath atomically:YES];
* 从"沙盒"中读取数据
1> 获取文件的路径
2> 调用NSArray、NSDictionary的xxxWithContentsOfFile
** 总结: 使用对象: 仅仅是Foundation框架中的一些类, 比如: NSString\NSArray\NSDictionary\NSSet\NSNumber\NSData
** 总结: 调用对象的writeToFile \ xxxWithContentsOfFile 方法来实现。
============================= 演示数据的读、写。通过"plist文件"来存储 =============================
============================= 演示数据的读、写。通过"Preference(偏好设置)"来存储。 =============================
* 使用"偏好设置"来存储数据, 本质上就是通过"plist"来存储数据, 但是使用起来更简单(无需关注文件、文件夹路径和名称)。
* 通过"偏好设置"的方式读、写文件时, 路径在"沙盒根目录" -> "Library" -> "Preferences"
* 使用步骤:
1> 创建一个访问"偏好设置"目录的对象NSUserDefaults对象
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // 获得单例对象
2> 通过"键值对"方式存储数据
[defaults setObject:@"value" forKey:@"key"];
[defaults setInteger:100 forKey:@"age"];
[defaults setBool:YES forKey:@"auto_login"];
3> 同步, 将内存中的数据写入文件。
[defaults synchronize];
** 注意: 如果不调用synchronize方法, 则由系统随机进行同步(什么时候同步不确定)。
4> 从"偏好设置"中读取数据
[defaults objectForKey:@"key"];
[defaults boolForKey:@"key"];
** 使用"偏好设置"存储数据的不足: 数据只能存储在一个文件中, 不存储大批量数据(很多时候大批量数据要分多个文件存储)
============================= 演示数据的读、写。通过"Preference(偏好设置)"来存储。 =============================
============================= 演示数据的读、写。通过"归档"的方式来存储。对象必须遵守NSCoding协议。 =============================
* 通过"plist"文件来保存数据, 无法直接将一个对象保存到文件中。比如Person对象就没有writeToFile方法。
* "归档"是一种可以把任何对象, 直接保存为文件的方式。(其中包括"归档"与"反归档(读档)")
* 归档: 对象 -> 文件
[NSKeyedArchiver archiveRootObject:person toFile:filePath];
* 反归档(读档): 文件 -> 对象
[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
* 通过"归档"的方式能将任何遵守了NSCoding协议的"对象"存储到文件中
* NSCoding协议的两个重要的方法:
1> - (void)encodeWithCoder:(NSCoder *)aCoder;
/**
** 作用: 对象归档时调用该方法(将对象写入文件时).
1> 说明哪些属性要存储
2> 说明如何存储这些属性
** 示例代码:
// 归档时调用该方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
[aCoder encodeDouble:self.height forKey:@"height"];
}
// 通过调用NSKeyedArchiver的archiveRootObject方法来实现归档
CZPerson *person = [[SteveZPerson alloc] init];
person.name = @"JackMeng";
person.age = 27;
person.height = 1.75;
// 获取沙盒路径
NSString *sandBoxPath = NSHomeDirectory();
// 获取Documents的路径
NSString *docPath = [sandBoxPath stringByAppendingPathComponent:@"Documents"];
// 获取文件路径
NSString *filePath = [docPath stringByAppendingPathComponent:@"person.plist"];
// 将对象person归档
[NSKeyedArchiver archiveRootObject:person toFile:filePath];
*/
2> - (id)initWithCoder:(NSCoder *)aDecoder;
/**
** 作用: 当从文件中解析对象时调用该方法.
1> 说明哪些属性要解析(读取)
2> 说明如何解析(读取)这些属性
** 示例代码:
// 读档时调用该方法
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.height = [aDecoder decodeDoubleForKey:@"height"];
}
return self;
}
// 获取沙盒路径
NSString *sandBoxPath = NSHomeDirectory();
// 获取Documents的路径
NSString *docPath = [sandBoxPath stringByAppendingPathComponent:@"Documents"];
// 获取文件路径
NSString *filePath = [docPath stringByAppendingPathComponent:@"person.bin"];
CZPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"name: %@, age: %ld, height: %f", person.name, person.age, person.height);
*/
* 如果父类中也有属性需要归档、读档, 在子类中必须调用super的相关方法。
/**
示例代码:
@implementation SteveZStudent
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
self.SNo = [aDecoder decodeObjectForKey:@"SNo"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:self.SNo forKey:@"SNo"];
}
@end
*/
============================= 演示数据的读、写。通过"归档"的方式来存储。对象必须遵守NSCoding协议。 =============================
***** 使用SQLite数据库存储, 当非常大量的数据存储时使用 *****
***** 使用Core Data存储, 就是对SQLite的封装 *****
1> 从iOS 5.0出现
2> 效率低下, 不需要懂SQL语句, 直接操作对象。
***** 使用Core Data存储, 就是对SQLite的封装 *****
***** 通过"网络"方式存储 *****