State Restoration 状态恢复
使用场景:比如在车主APP创建订单的时候,已经填了一部分表单,比如已经选择了购买方式,提成点等。。。然后,此时来了一个电话,聊了比较久的时间,久到APP在后台已经被系统kill了,此时,挂断电话,进入车主APP,刚才填写的表单全部都没有了,整个APP都是重新启动的状态。。。
针对以上描述的类似场景,我们如何来提升用户体验呢?
其实苹果早在2016年就提出了状态恢复的概念,也提供了相应的API,只是一直被忽略,没有应用起来,也不造为啥,下面来详细介绍一下
使用步骤
1.首先创建个工程,然后viewcontroller中加两textfield
2.在应用中启用状态保存和恢复
- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder {
return true;
}
- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder {
return true;
}
3.设置恢复标识
恢复标识就是一个简单的字符串,它实际内容是个啥并不重要,只要保持唯一性就好了。
- 方式一
Storyboard ID也可以作为唯一标识
- 方式二
self.restorationIdentifier = @"restorationIdentifier";
在故事板或者在代码中都可以设置恢复标识Restoration ID,这里需要重复检查一下,确保我们需要状态恢复的每一个VC都设置了唯一的Restoration ID
这里设置Restoration ID的意义在于形成应用程序中任何视图控制器的唯一路径,比如说viewControllerA的路径是RootTabBarController / NavigationController /HomeViewController/ viewControllerA
做到这一步,我们就可以run一下工程看看效果,我这里demo写的比较简单,没有push多层页面,只push了一层,原理是一样的,已经可以恢复到页面级别了,但是页面上的元素修改还是没办法恢复
4.The UIStateRestoring Protocol
其实在进行状态恢复的时候,UIKit帮我们做了很多事情,然后我们要做的就是告诉UIKit哪些view,VC需要被恢复。这一步就需要实现UIStateRestoring协议了,在状态被保存和恢复时都会有相应的协议方法被调用。
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder;
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder;
- (void) applicationFinishedRestoringState;
做到这一步遇到一个问题,其他VC都是在main.storyBoard中创建并设置Restoration ID的,只有ViewControllerA是手动创建的,在恢复过程中,只能恢复到有ViewControllerA的上一级页面,并且控制台打印了下面这个Warning
根据提示去修改代码让有ViewControllerA实现UIViewControllerRestoration协议,这个协议里面只有这一个类方法,看方法名应该是需要返回一个需要被恢复状态的vc
+ (nullable UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder
于是,简单实现一下
+ (nullable UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder {
ViewControllerA *vc = [[ViewControllerA alloc]init];
vc.restorationIdentifier = identifierComponents.lastObject;
vc.restorationClass = [self class];
return vc;
}
再测试一下,果然可以恢复到ViewControllerA了,这里思考下应该是通过SB创建的类和手动创建的类,UIKit恢复的机制不同导致
为了方便调试,可以在info.plist中设置Application does not run in background 为YES
总结:下次应用启动的时候会自动寻找保存状态的文件,如果有的话就恢复。但是这些文件只适用于上次和当前的周期,在启动后会删除上次保存状态的文件。在恢复过程中有错误也会删除保存状态文件。例如,在一次恢复过程中应用崩溃了,那么系统会自动删除文件防止下次恢复再崩溃
demo链接:github.com/AnleSu/Stat…