APP State Restoration

概述

状态保存和恢复:保存app原来的界面,APP被系统中断后恢复之前的状态,文档描述如下:
Preserving Your App's UI Across Launches,Return your app to its previous state after it is terminated by the system.
举个例子,假如在编辑一篇文档,没有保存,此时如果app被系统杀死了,重新启动编辑的数据就没了,有了这个功能,就能恢复到杀死前的状态

知识点:什么情况下APP会被系统终止

在官方文档里找到这样一句话:
The system usually terminates apps so that it can reclaim memory and make room for other apps being launched by the user, but the system may also terminate apps that are misbehaving or not responding to events in a timely manner.
就是说系统通常终止APP来回收内存和为用户启动其它APP时提供内存空间,但是系统也会在APP出现异常行为或者没有及时响应事件时终止APP。

大概原理:

保存阶段,调用shouldSaveApplicationState方法,返回true则从跟控制器开始,调用有restorationIdentifier的各个控制器的encodeRestorableState方法保存数据,也就是状态数据,注意不要再这个方法里保存应该持久化的数据,应该是临时数据,并且可有可无,不影响主要功能的数据;恢复阶段,调用shouldRestoreApplicationState方法,返回true则从跟控制器开始,获取有restorationIdentifier的各个控制器对象,调用这些对象的decodeRestorableState方法恢复数据。

实现步骤

1. 为APP启用状态保存和恢复功能

实现app delegate 的shouldSaveApplicationState和shouldRestoreApplicationState两个方法就行。这两个方法分别决定了保存阶段和恢复阶段是否会发生,有时候保存或者恢复不合适的时候可以返回false

    func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
        print("shouldSaveApplicationState")
        return true
    }
    
    func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
        print("shouldRestoreApplicationState")
        return true
    }

2. 给你想要状态保存的view controllers设置恢复标识

如果控制器是通过storyboard初始化,在Restoration ID框中填入一个字符串就行,一般是类名,如果是通过代码初始化,在运行时给控制器的RestorationIdentifier属性赋值一个字符串

3. 如果需要的话,在恢复期间重新创建view controllers

如果是storyboard初始化,这一步不需要处理,代码初始化则要手动初始化,就是将实现UIViewControllerRestoration代理的一个类赋值给restorationClass属性:

class EditingViewController: UIViewController {
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.restorationClass = EditingViewController.self
        self.restorationIdentifier = "EditingViewController"
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension EditingViewController: UIViewControllerRestoration {
    static func viewController(withRestorationIdentifierPath identifierComponents: [String], coder: NSCoder) -> UIViewController? {
        let vc = ViewController(nibName: nil, bundle: nil)
        return vc
    }
}

也可以用APPDelegate的viewControllerWithRestorationIdentifierPath方法替代,在纯代码设置根控制器时用这个方法比较好,因为要替换window的根控制器

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
        let rootVC = ViewController(nibName: nil, bundle: nil)
        self.window?.rootViewController = rootVC
        self.window?.makeKeyAndVisible()
        return true
    }

func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [String], coder: NSCoder) -> UIViewController? {
        let vc = ViewController(nibName: nil, bundle: nil)
        window?.rootViewController = vc//切换更控制器
        return vc
    }

4.实现保存和恢复的两个方法,分别在保存阶段和恢复阶段调用

 override func encodeRestorableState(with coder: NSCoder) {
        super.encodeRestorableState(with: coder)
        let text = textField.text
        let isFirst: Bool = textField.isFirstResponder
        coder.encode(text, forKey: "textFieldText")
        coder.encode(isFirst, forKey: "isFirstResponder")
    }
    
    override func decodeRestorableState(with coder: NSCoder) {
        super.decodeRestorableState(with: coder)
        let text = coder.decodeObject(forKey: "textFieldText") as? String
        let isFirst = coder.decodeBool(forKey: "isFirstResponder")
        textField.text = text
        if isFirst {
            textField.becomeFirstResponder()
        }
    }

注:

  • 在任务管理器里手动杀死APP不会触发Restoration
  • 如果是利用纯代码恢复window的根控制器,要记得把restoration阶段初始化的控制器设置为根控制器,并且要将设置根控制器的代码移动到willFinishLaunchingWithOptions,代码如上

demo地址:

https://github.com/zhouweijie/demos.git

参考资料:

  • Preserving Your App's UI Across Launches
  • About the UI Preservation Process
  • About the UI Restoration Process
  • Saving and Restoring Application State on iOS
  • What's New in State Restoration

你可能感兴趣的:(APP State Restoration)