不同的应用有不同的需求,但是有些行为是大多数类型的应用都需要的。以下部分提供了有关如何在应用中实现几个特定功能类型的指导。
隐私策略
保护用户的隐私是应用设计阶段需要重点考虑的问题。隐私保护包括保护用户的数据、用户的身份识别信息、以及个人信息。系统框架已经为管理数据(例如通讯录)提供了隐私控制,但是应用应该采取措施来保护自身的数据。
使用磁盘加密来保护数据
使用内置硬件来存储经过磁盘格式加密的文件,并根据需要进行解密。当用户设备被锁定时,保护文件无法访问,即使是创建它们的应用。用户必须解锁设备(通过输入相应的密码)应用才能够访问被保护的文件。
绝大多数iOS设备都提供数据保护。数据保护也取决于如下必要条件
- 用户设备上的文件系统必须支持数据保护,大多数设备都支持此项行为。
- 用户必须为设备设置密码锁。
为了保护文件,你要为文件添加一个属性,用来指明想要的保护级别。可以使用NSData类或者NSFileManager类来添加这个属性。当写入新文件时,你可以使用 NSData类的writeToFile:options:error:方法(带有合适的写入选项参数值)。对于已存在的文件,你可以使用NSFileManager类的setAttributes:ofItemAtPath:error:方法来设置或改变NSFileProtectionKey的值。当使用这些方法时,为文件指定一个保护级别。保护级别如下所示:
- 没有保护——文件已加密,但不受密码保护,并在设备锁定时可用。指定NSDataWritingFileProtectionNone 选项 (NSData) 或NSFileProtectionNone 属性 (NSFileManager).。
- 完全保护——文件已加密,并且在设备锁定时无法访问。指定 NSDataWritingFileProtectionComplete 选项 (NSData)或NSFileProtectionComplete 属性 (NSFileManager).
- 完全保护,除非已经打开——文件已加密。当设备锁定时,关闭的文件不可访问。但是如果锁定前文件是打开的,那么锁定后文件依然可被访问。指定NSDataWritingFileProtectionCompleteUnlessOpen 选项 (NSData) 或 NSFileProtectionCompleteUnlessOpen 属性 (NSFileManager).
- 完全保护,直到首次登录——文件已加密且无法访问,直到设备已启动且用户解锁过一次之后。指定NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication 选项 (NSData) 或者NSFileProtectionCompleteUntilFirstUserAuthentication 属性 (NSFileManager).
如果你要保护文件,你的应用必须准备好失去这个文件的访问权。当完全文件保护被启用时,应用在用户锁定设备的时候失去对文件读写的能力。你可以跟踪状态的改变以便使用下面的技术来保护文件:
- 应用委托实现applicationProtectedDataWillBecomeUnavailable: 和 applicationProtectedDataDidBecomeAvailable: 方法.
- 任何对象都可以注册UIApplicationProtectedDataWillBecomeUnavailable 和 UIApplicationProtectedDataDidBecomeAvailable 通知.
- 任何对象都可以检查UIApplication对象的protectedDataAvailable属性,来确定文件当前是否可以访问。
对于新文件,推荐你在写入文件前启用数据保护。如果你正在使用writeToFile:options:error:方法写入一个NSData对象到磁盘,那么它自动就实现了数据保护。对于已存在的文件,使用新的受保护的版本替换旧的不受保护的版本来实现数据保护。
识别应用的唯一用户
识别应用的用户可以带来明确的好处。如果你只需要区别应用不同的用户,iOS提供了标识符来帮助完成此功能。但是,如果你需要高级别的安全性,你可能需要做更多工作。例如,一个提供金融服务的应用会希望提示用户提供登录凭证,以确保用户被批准访问特定账户。
重要:当识别用户时,始终要明确表达你打算使用获取的信息做什么。识别用户以便跟踪他们的行为是不可接受的。
以下是一些可能需要你识别用户的常见情况,以及如何实现它们的解决方案:
- 你想连接用户到服务器上的特定账户。包活一个要求用户安全地输入他们账户信息的登录界面。总是通过以加密格式保存从用户处搜集的账户信息以保证安全。
- 你需要区分在不同设备上运行的实例。使用UIDevice类的identifierForVendor属性来获取一个ID。一个用户可以有多个设备,该ID值在每个设备上都不同。
- 你想因广告的目的来识别用户。使用ASIdentifierManager类的advertisingIdentifier属性来获取用户的ID。
因为用户被允许在所有他们的设备上运行应用,苹果公司不提供识别同一个用户在不同设备上的方式。如果你需要识别特定的用户,你必须使用UUIDs、登录账号、或者其他类型的身份识别系统来提供你自己的解决方案。
遵守限制
用户可以设置限制,这种限制指明要在应用中使用的媒体的评级。如果你的应用基于限制播放媒体或修改媒体的行为,你需要确定当前的设置以及在设置改变时进行响应。
想要得到当前的设置,获取standardUserDefaults对象并使用objectForKey:方法来查看下面这些键的值:
媒体评级键 | 值 |
---|---|
com.apple.content-rating.ExplicitBooksAllowed | Boolean。如果值为NO,则露骨的书本不被允许。 |
com.apple.content-rating.ExplicitMusicPodcastsAllowed | Boolean。如果值为NO,则露骨的音乐、电影、以及播客节目都不被允许。 |
com.apple.content-rating.AppRating | NSNumber。该键的值在0-1000的范围内。应用的评级不允许超过当前值。 |
com.apple.content-rating.MovieRating | NSNumber。该键的值在0-1000的范围内。电影的评级不允许超过当前值。 |
com.apple.content-rating.TVShowRating | NSNumber。该键的值在0-1000的范围内。TV内容的评级不允许超过当前值。 |
注意:如果objectForKey: 对于特定键返回nil,这意味着关于此特定限制的信息不可用。应用可以使用它自己的政策来决定合适的评级。
要查明何时用户更改了限制,请注册NSUserDefaultsDidChangeNotification通知。standardUserDefaults对象在应用检测到一个持久域(persistent domains)中的首选项发生更改的时候,发送这个通知给应用。
应用评级是针对国家代码定义的,并得到广泛应用的。表5-1展示了美国应用评级相关联的值。
Table 5-1 应用评级
评级名称 | 数值 |
---|---|
4+ | 100 |
9+ | 200 |
12+ | 300 |
17+ | 600 |
电影和电视的评级因国家不同而异。如果国家或地区没有为电影或电视节目指定评级系统,应用应该使用它自己的合适地评级策略。虽然大多数地区定义了电影评级,但只有少数地区定义了电视节目的评级。
一个地区可以定义几个评级级别,每个级别与一个描述评级的名字和一个评级0-1000的范围。例如,美国使用字符串“G”和数字100来指定最低一级的电影评级级别。
即使应用不播放媒体,你也可能想把你自己的评级系统映射到电视节目评级系统上。例如,游戏可以只有当美国电影评级为“R”被允许的时候才可以启用某些功能。想要查看当前的评级列表,请下载本文档的附件(链接位于文档底部)。
支持多个iOS版本
支持最新以及较早iOS版本的应用,必须使用运行时来检测来阻止在老版本上运行新API。当应用尝试使用当前操作系统不允许的功能时,运行时检查可以防止此种情况下崩溃的发生。
以下是你可以使用的几个检查类型。
- 要确定一个类是否存在,就看它的Class对象是否为nil。使用下面类似的方法进行判断。
if ([UIPrintInteractionController class]) {
// Create an instance of the class and use it.
}
else {
// The print interaction controller is not available so use an alternative technique.
}
- 想要确定现有类中是否有一个方法可用,使用instancesRespondToSelector:类方法,或者respondsToSelector:对象方法。
- 想要判断基于C的函数是否可用,执行函数名与NULL的比较。如果符号不是NULL,就可以调用函数。例如:
if (UIGraphicsBeginPDFPage != NULL) {
UIGraphicsBeginPDFPage();
}
更多关于如何编写代码以支持多开发目标的信息和例子,参见SDK Compatibility Guide。
启动的时候保留应用的视觉外观
即使你的应用支持后台运行,它也不是永远运行。在有些时候,系统可能会需要终止应用来为当前的前台应用释放空间。但是,用户应该永远不需要关心应用是否在运行。从用户的角度看,退出应用看上去和临时中断是一样的。当用户回到应用时,应用应该总是回到之前退出时的位置,这样用户就能继续之前的任务了。该行为提供了一个很好的用户体验,而且UIKit内置这些转换状态,所以相对容易实现。
UIKit内建的状态保存系统提供了简单但灵活的基础功能。这些基本功能的工作是在合适的时候驱动保存和恢复的进程。要想做到这点,UIKit需要来自应用的帮助。因为只有你理解你应用的内容,所以只有你才能写保存和恢复内容的代码。当你更新应用的UI的时候,也只有你知道如何把旧的储存的内容映射到界面中新的对象中。
有三个你必须考虑状态保存的地方:
- 应用的委托对象,它管理应用的顶层状态
- 应用的视图控制器对象,它管理应用用户界面的整体状态
- 应用自定义视图,可能有一些需要保存的自定义数据
UIKit允许你选择用户界面的局部进行保存。如果你已经有自定义的代码来处理状态保存,你可以继续使用这些代码,并根据需要把部分移动到UIKit的状态保存系统。
在应用中启用状态保存和恢复
状态保存和恢复不是自动功能,应用必须选择使用它。应用通过实现它的委托中的如下方法来表明它对该功能的支持:
application:shouldSaveApplicationState:
application:shouldRestoreApplicationState:
通常,你的这些方法的实现要返回YES,以便表明这个状态存储和恢复能够发生。但是,如果不想让此功能发生,可以让方法返回NO。例如,在释放和更新应用之后,如果应用不能有效的从之前的版本回复状态,你可以让application:shouldRestoreApplicationState:方法返回NO。
(未完待续......)