iOS沙盒机制(1)
•iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被称为沙盒 •所有的非代码文件都要保存在此,例如图像、图标、声音、映像、属性列表、文本文件等 –
1) 每个应用程序都有自己的存储空间 –2) 应用程序不能翻过自己的围墙去访问别的存储空间中的内容 –3) 应用程序请求的数据都要通过权限检测,假如不符合条件,不会被放行
iOS沙盒结构分析 •应用程序包:(Bundle)包含了所有的资源文件和可执行文件 • •Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录 • •Library
/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积较大、不需要备份的非重要数据 • •Library/Preference:保存应用的所有偏好设置,iOS的设置应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录 • •tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录


 

沙盒目录常用获取方式(1)
获取程序的Home目录
NSString *home = NSHomeDirectory();

注意:
虚拟机Home目录:
/Users/userName/Library/Application Support/iPhone Simulator/6.1/Applications/C926CCFA-A110-45E2-B4AD-7E5679152D99
真机Home目录:
/var/mobile/Applications/304D8530-98CB-4043-A208-EBF06E8ADBB9

沙盒目录常用获取方式(2)
获取Documents目录

// 2、获取Documents目录
// NSUserDomainMask 代表从用户文件夹下找
// YES 代表展开路径中的波浪字符“~”
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 只有一个匹配目录,所以这个集合里面只有一个元素
NSString *doc = documents[0];

// 使用字符串拼接的方式获取目录名
NSString *doc2 = [home stringByAppendingPathComponent:@"Documents"];

注意:
不建议采用字符串拼接的方式获取目录,因为新版本的操作系统可能会修改默认目录名称。

沙盒目录常用获取方式(3)
获取Cache目录
NSArray *caches = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cache = caches[0];

Preferences目录
通过NSUserDefaults类存取该目录下的设置信息

获取Tmp目录
NSString *tmpDir = NSTemporaryDirectory();

 

技巧:在Mac显示隐藏文件的方法
显示Mac隐藏文件的命令:
defaults write com.apple.finder AppleShowAllFiles -bool true

隐藏Mac隐藏文件的命令:
defaults write com.apple.finder AppleShowAllFiles -bool false

注意:需要重启Finder

另外, 在Finder中,按shift+command+g,然后输入:

/Users/username/Library/Application Support/iPhone Simulator/6.1/Applications

也可以进入虚拟机应用程序目录,其中username是本机用户名

 

iOS应用数据存取的常用方式

XML属性列表 —— PList
NSKeyedArchiver 归档
Preference(偏好设置)
SQLite3 
Core Data
XML属性列表——PList

属性列表是一种XML格式的文件,扩展名为plist

如果对象是NSArray、NSDictionary类型,可以使用writeToFile:atomically:方法直接写入到属性列表文件
如果对象是NSString、NSData类型,也可以使用writeToFile:atomically:方法写入对应的文件

说明:atomically(写入原子性)
YES:先创建一个临时文件,直到内容完成后再导入目标文件
NO:直接写入文件

注意:如果所指定保存文件的路径不存在,写入文件方法不会报错,文件也不会被保存!
属性列表的局限性

只有支持的数据类型可以被序列化,存储到plist中。无法将其他Cocoa对象存储到plist,不能存储自定义对象
支持的数据类型:
Array
Dictionary

Boolean
Date
Number
String

•将NSArray写入沙盒文件

•将NSDictionary写入沙盒文件
 
其他格式数据的保存

NSString —— 保存时需要自定字符串编码

UIImage —— 注意UIImage无法写入文件,需要使用NSData数据类型进行中转,NSData可以将任何类型的文件,以二进制格式存储

// 生成图像数据
NSData *data = UIImagePNGRepresentation(image);
Archiver & Unarchiver归档和恢复
特点:
支持复杂的数据对象,包括自定义对象
对自定义对象进行归档处理,对象中的属性需要是基本数据类型,或者是实现了NSCoding协议的对象实例
自定义对象的类也需要实现NSCoding

应用场合
在本地保存自定义对象或数组
保存游戏状态
在网络间传输自定义对象数据
……
Archiver & Unarchiver归档和恢复
特点:
支持复杂的数据对象,包括自定义对象
对自定义对象进行归档处理,对象中的属性需要是基本数据类型,或者是实现了NSCoding协议的对象实例
自定义对象的类也需要实现NSCoding

应用场合
在本地保存自定义对象或数组
保存游戏状态
在网络间传输自定义对象数据
……
NSKeyedArchiver

NSString、NSDictionary、NSArray、NSData、NSNumber等类型的对象,可以直接用NSKeyedArchiver进行归档和恢复

不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以
NSCoding协议方法

encodeWithCoder:
每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:方法归档实例变量

initWithCoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey:方法解码实例变量

NSCoding协议方法的调用
[NSKeyedArchiver archiveRootObject:toFile:]

会首先调用被归档类对象的encodeWithCoder方法对该对象的属性编码,然后再写入文件进行归档

[NSKeyedUnarchiver unarchiveObjectWithFile:path]

从文件加载数据后,会调用类的initWithCoder方法,实例化该类对象,并恢复属性

NSKeyedArchiver——归档对象的注意
如果父类也遵守了NSCoding协议,需要注意:

在encodeWithCoder:方法中加上一句
[super encodeWithCoder:aCoder];
确保继承的实例变量也能被编码,即也能被归档

在initWithCoder:方法中加上一句
self = [super initWithCoder:aDecoder];
确保继承的实例变量也能被解码,即也能被恢复
偏好设置——写入

很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能
每个应用都有个NSUserDefaults实例,通过它来存取偏好设置
例如:保存用户名、字体大小、是否自动登录
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"itcast.cn" forKey:@"userName"];
[defaults setFloat:18.0f forKey:@"fontSize"];
[defaults setBool:YES forKey:@"autoLogin"];

偏好设置——读取

// 读取系统偏好
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userName = [defaults objectForKey:@"userName"];
float fontSize = [defaults floatForKey:@"fontSize"];
BOOL autoLogin = [defaults floatForKey:@"autoLogin"];

注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘,应用程序就终止了。

出现以上问题,可以通过调用synchornize方法强制写入:
[defaults synchronize];

 

posted on 2015-02-08 17:03  HJiang  阅读(341)  评论(0编辑  收藏  举报