• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Swift App状态恢复

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原创Blog位置:

https://blog.csdn.net/hello_hwc/article/details/45146305 

前言: 
对于一个app来说,没有办法保证每次都是用户正常关闭(双击home,然后关闭)。有可能是用户把app切换到后台,然后由于内存的原因,IOS系统选择关闭掉应用。这时候,就是状态恢复使用的场景。App应当做到的是,用户没有察觉到App在后台被IOS Kill掉了。

本文主要讲诉如何用Storyboard进行状态恢复,下一篇更新如何实现代码State Restoration。

注意: 
状态恢复不是持久化存储,换句话说,用户正常关闭App的时候,状态恢复是不会起到任何作用的,因为用户正常关闭App,理所应当这次操作的状态都应该清除。

一 什么是状态相关的信息?
就是那些不容易被重新创建的信息,比如一个tableview,当前选择的是哪行?比如用户的first responser是什么?比如tabController当前选择是哪个页面。

二 如何实现保存状态信息
(必须) app 代理的两个代理方法,要实现。通常直接返回YES即可,当然,也可以判断状态来决定是否保存和恢复。 
application:shouldSaveApplicationState: application:shouldRestoreApplicationState:
(必须)每个想要保存的视图控制器一定要有一个唯一的恢复表示符(restoration identifiers)。如果是用Storyboard上创建的,则在storyboard上设置。如果是代码创建的,使用属性restorationIdentifier 。
(必须)对于storyboard上创建的视图控制器,不需要设置restoration classes。对于那些由代码动态创建的视图控制器,要设置restoration classes来实现保存和恢复。否则,统一在appDelegate的代理方法中实现。后一种方式不推荐。
(推荐)实现两个方法来保存/恢复状态信息
  encodeRestorableStateWithCoder: 
  decodeRestorableStateWithCoder: 

另外,可以使用App 代理来存储版本等额外信息

application:willEncodeRestorableStateWithCoder: and application:didDecodeRestorableStateWithCoder:

三 State Restoration的流程
保存状态的流程图 


恢复状态的流程图 

从视图控制器的生命周期来看

 awakeFromNib
 viewDidLoad
 decodeRestorableStateWithCoder:
 viewWillAppear
 viewDidAppear

如果是用代码实现的

 +viewControllerWithRestorationIdentifierPath:coder:
 awakeFromNib
 viewDidLoad
 decodeRestorableStateWithCoder:
 viewWillAppear
 viewDidAppear

注意:比如v3->v2->v1,是层次结构,如果v2没有标识符,那么底层的v3即便有标识符也没办法恢复。一组层次结构要保存,一定要都有restorationIdentifier

四 Demo
项目链接 
https://github.com/wenchenhuang/StateRestorationStoryboard

如何测试 
在XCode中运行,然后Command+Shift+H进入后台,然后点击Stop的方框,然后再运行,会发现恢复了上次的状态

首先,在AppDelegate中实现两个代理函数

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

然后,看一下我的Storyboad上的架构 

一个tabbarController,包括两个子Controller,然后第二个子Controller又包含一个ChildController

对每一个Storyboard上的vc都设置restoration identifiers,如图 


对Tabbar当前选择哪个VC进行保存恢复

let KTABBARSELECTINDEX = "SelectIndex"

class MainTabbarController:UITabBarController{
    override func encodeRestorableStateWithCoder(coder: NSCoder) {
        let selectindex = self.selectedIndex;
        coder.encodeInteger(selectedIndex, forKey: KTABBARSELECTINDEX)

        //Do not forget to call super
        super.encodeRestorableStateWithCoder(coder)
    }
    override func decodeRestorableStateWithCoder(coder: NSCoder) {
        let selectindex = coder.decodeIntegerForKey(KTABBARSELECTINDEX)
        self.selectedIndex = selectindex
        //Do not  forget to call super
        super.decodeRestorableStateWithCoder(coder)
    }

}

对FirstViewController的TextField内容进行保存/恢复

let KSECONDVCTEXTFIELD = "secondvctextField"

class FirstViewController:UIViewController,UITextFieldDelegate{

    @IBOutlet weak var textfield: UITextField!
    override func encodeRestorableStateWithCoder(coder: NSCoder) {
        coder.encodeObject(textfield.text, forKey: KSECONDVCTEXTFIELD)
        super.encodeRestorableStateWithCoder(coder)
    }
    override func decodeRestorableStateWithCoder(coder: NSCoder) {
        if let text = coder.decodeObjectForKey(KSECONDVCTEXTFIELD) as? String{
            textfield.text = text
        }
        super.decodeRestorableStateWithCoder(coder)
    }
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textfield.resignFirstResponder()
        return true
    }
}


对SecondViewController进行Textfield和ChildVC进行保存/恢复

let KFIRSTVCTEXTFIELD = "firstvctextField"

class SecondViewController:UIViewController,UITextFieldDelegate
{
    @IBOutlet weak var textfield: UITextField!
    override func encodeRestorableStateWithCoder(coder: NSCoder) {
        coder.encodeObject(textfield.text, forKey: KFIRSTVCTEXTFIELD)
        //Parent vc should encode child vc,so that child vc can encode itself
        let childVC = self.childViewControllers.first as! UINavigationController
        coder.encodeObject(childVC, forKey: "childVC")
        super.encodeRestorableStateWithCoder(coder)
    }
    override func decodeRestorableStateWithCoder(coder: NSCoder) {
        if let text = coder.decodeObjectForKey(KFIRSTVCTEXTFIELD) as? String{
            textfield.text = text
        }
        super.decodeRestorableStateWithCoder(coder)
    }
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textfield.resignFirstResponder()
        return true
    }
}

对嵌入式的TableViwController进行当前选择的行进行保存/恢复

let KTALBLESELECTEDINDEX = "selectIndex"

class EmbedTableviewController:UITableViewController{

    override func encodeRestorableStateWithCoder(coder: NSCoder) {
        if let selectedIndexs = self.tableView.indexPathsForSelectedRows(){
            //Encode select index
            var data = NSKeyedArchiver.archivedDataWithRootObject(selectedIndexs)
            coder.encodeObject(data, forKey:KTALBLESELECTEDINDEX)
        }
        super.encodeRestorableStateWithCoder(coder)
    }
    override func decodeRestorableStateWithCoder(coder: NSCoder) {

        var data = coder.decodeObjectForKey(KTALBLESELECTEDINDEX) as? NSData
        if data != nil{
            //Decode select index
            if let selectedIndexs = NSKeyedUnarchiver.unarchiveObjectWithData(data!) as? NSArray{
                for var i = 0;i < selectedIndexs.count;i++ {
                    let oneIndex = selectedIndexs[i] as! NSIndexPath
                    self.tableView.selectRowAtIndexPath(oneIndex, animated:false, scrollPosition: UITableViewScrollPosition.None)
                }
            }
        }
        super.decodeRestorableStateWithCoder(coder)
    }
}
 

 

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
swift学习笔记之-访问控制发布时间:2022-07-14
下一篇:
理解 Swift:Objective-C 的构建管道发布时间:2022-07-14
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap