系统在保存应用状态时,首先会查询UIWindow对象rootViewController的restorationIdentifier(恢复标识)属性,如果rootViewController具有restorationIdentifier属性,那么系统会保存其状态;然后,系统会遍历rootViewController的子视图控制器,并保存它们的状态;接下来继续遍历这些视图控制器的子视图控制器……直到层次结构的最后一级。如果其中某个视图控制器没有restorationIdentifier属性,那么系统不会保存该视图控制器及其所有子孙视图控制器的状态,无论子孙视图控制器是否具有restorationIdentifier属性。
例如,在图24-2中,应用有两个用灰色标识的视图控制器,它们没有恢复标识,因此系统无法恢复其状态,也无法恢复其子视图控制器的状态。
图24-2 恢复标识
根据Apple命名规范,通常应该将类名作为类的恢复标识。打开BNRAppDelegate.m,在application:didFinishLaunchingWithOptions:中为UINavigationController对象设置恢复标识:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc]
initWithFrame:UIScreen.mainScreen.bounds]];
BNRItemsViewController *itemsViewController =
[[BNRItemsViewController alloc] init];
// 创建一个UINavigationController对象,
// 其根视图控制器是itemsViewController
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:itemsViewController];
// 将UINavigationController对象的类名设置为恢复标识
navController.restorationIdentifier =
NSStringFromClass([navController class]);
// 将UINavigationController对象设置为UIWindow的rootViewController
self.window.rootViewController = navController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
现在UINavigationController对象已经有了恢复标识,系统会保存该对象的状态,同时,如果该对象的子孙视图控制器有恢复标识,系统也会保存它们的状态。
对于BNRItemsViewController和BNRDetailViewController,应该在指定初始化方法中设置其恢复标识。除此之外,还需要为两个视图控制器设置恢复类(restoration class)。系统在恢复某个对象的状态时,会要求其恢复类创建该对象。
打开BNRItemsViewController.m,修改init方法,设置恢复标识和恢复类:
- (instancetype)init
{
// 调用父类的指定初始化方法
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
UINavigationItem *navItem = self.navigationItem;
navItem.title = @“Homepwner”;
self.restorationIdentifier = NSStringFromClass([self class]);
self.restorationClass = [self class];
对于BNRDetailViewController,则应该在initForNewItem:方法中设置:
- (instancetype)initForNewItem:(BOOL)isNew
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.restorationIdentifier = NSStringFromClass([self class]);
self.restorationClass = [self class];
if (isNew) {
最后,还要为添加BNRItem对象时以模态形式推入的UINavigationController对象设置恢复标识。
重新打开BNRItemsViewController.m,修改addNewItem:方法,代码如下:
- (IBAction)addNewItem:(id)sender
{
// 通过BNRItemStore单例创建一个新的BNRItem对象
BNRItem *newItem = [[BNRItemStore sharedStore] createItem];
BNRDetailViewController *detailViewController =
[[BNRDetailViewController alloc] initForNewItem:YES];
detailViewController.item = newItem;
detailViewController.dismissBlock = ^{
[self.tableView reloadData];
};
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:detailViewController];
navController.restorationIdentifier =
NSStringFromClass([navController class]);
(请注意,以上代码并没有为两个UINavigationController对象设置恢复类,它们将由应用程序委托负责创建,下一节会介绍相关过程。)
现在,Homepwner中所有视图控制器都已经具有了恢复标识,当应用进入后台运行或被终止时,系统会保存所有视图控制器的状态。