前言
据存储本质就是运行时的对象保存在文件、数据库中。数据存储可以分为两步:首先是将对象转换成二进制数据,这一步也叫序列化;相反,将二进制数据转换成对象则称为反序列化;然后是考虑二进制数据如何保存和读取。
沙盒目录
iOS系统为每个App分配了独立的数据目录,App只能对自己的目录进行操作,这个目录所在被称为沙盒目录。
一个应用的沙盒包括下面三个部分:应用目录、沙盒目录、iCloud目录。
Documents目录用于保存App的数据,包括App运行时需要的各类文件以及用户的数据等。Documents文件夹可以在连接iTunes时选择备份,通常Documents目录用来存放可以对外的文件。
Library目录用来保存不对外的数据,但同样可以被iTunes备份(Library/Caches目录除外,原因就和目录名一样,里面应该只放Caches)。Library/Caches目录用来放置运行时产生的临时文件以及缓存文件,空间不足时可能会被iOS系统删除。Library/Preferences目录通常用于保存用户的设置等信息,比如我们常用的NSUserDefaults类就会以plist的方式保存在该目录中。
tmp目录用来保存不重要的临时文件,在系统重启后会被清空,容易知道这个也不会被iTunes备份。
1 | // 获取沙盒根目录路径 |
我们工程中的图片资源是不是放在沙盒目录中呢?
工程中的资源文件在NSBundle,而NSBundle会被打包到.ipa文件上传到App Store,而用户安装App时候,会把App放置在应用目录(非沙盒目录)。
NSBundle
在用NSFileManager去读取文件的时候需要提供文件路径,但是有时候我们并不知道资源被放置在哪个目录,此时可以用到NSBundle。
在Xcode编译运行的时候,会把Xcode内的图片、xib、音频等都拷贝到.app文件中。
NSBundle就是系统提供,用来读取这些资源的类
NSBundle * mainBundle = [NSBundle mainBundle];
这样我们就拿到我们的mainBundle,通过mainBundle我们可以查找对应的资源:
NSString *path =[mainBundle pathForImageResource:@”some_pic_name”]; // 查找图片地
也可以通过mainBundle直接加载xib:[[NSBundle mainBundle] loadNibNamed:@"SSProgressView" owner:self options:nil];
通过CocoaPods安装的Pod库,要如何读取其资源?
1 | NSString *path = [[NSBundle mainBundle] pathForResource:@"SSTestPod" ofType:@"bundle"]; |
Keychain
保存在沙盒目录的数据是不安全的,用户可能会导出沙盒数据进行分析。
有没有什么保存方式是更安全的呢?
iOS给出的答案是keychain。
keychain是iOS提供给App存储敏感和安全相关数据用的工具。keychain同样会被iTunes备份,即使App重装仍能读取到上次保存的结果。为了保证数据安全,keychain内的数据都是经过加密。
1 | import <Security/Security.h> |
以KeychainWrapper为例,来看看封装后更简单的接口。
1 | - (void)savePassword:(NSString *)password; |
具体的使用样例:
1 | KeychainWrapper *wrapper = [[KeychainWrapper alloc] initWithSevice:kKeychainService account:self.account accessGroup:kKeychainAccessGroup]; |
要保存在keychain,即使应用卸载重装,仍旧能读取到该值。
对象序列化
NSCoding是系统提供的序列化协议,在对象转换为二进制的时候,会通过NSCoding的方法回调开发者。
1 | @protocol NSCoding |
1 | @interface SSUser : NSObject <NSCoding> |
YYModel具有几大特点:
1、利用iOS的Runtime特点,无需继承;
2、安全转换数据类型,常见Crash都进行了保护;
3、扩展性强,提供多种容器扩展;