[譯] 狀態恢復入門教程

在這篇狀態恢復教程中,咱們將瞭解如何使用 Apple 的狀態恢復接口來提高用戶的應用體驗。前端

注意:Xcode 7.三、iOS 9.3 和 Swift 2.2 已於 2016-04-03 更新。android

在 iOS 系統中,狀態恢復機制是一個常常被忽略的特性,當用戶再次打開 app 的時候,它可以精確的恢復到退出以前的狀態 - 而不用關心發生了什麼。ios

某些時候,操做系統可能須要從內存中刪除你的應用;這可能會嚴重中斷用戶的工做流。你的用戶不再必擔憂由於切換到另外一個應用而影響到工做的事情了。這就是狀態恢復機制所起到的做用。git

在這篇恢復教程中,你將更新現有應用以添加保留和恢復功能,並在其工做流可能被中斷的狀況下提高用戶體驗。github

入門

下載本教程的 入門項目。該應用名爲「Pet Finder」;對於那些碰巧在尋找毛茸茸貓科動物陪伴的人來講,這是一款方便的應用。swift

運行該應用;你將會看到一張關於貓的圖片,這表明你有機會能夠領養它:後端

Pet Finder

向右滑動便可與新的毛茸茸的朋友配對;向左滑動表示你想要繼續傳遞這個絨毛球小貓。你能夠從匹配選項卡欄中查看當前全部的匹配列表:app

Matches

點擊來查看所選中朋友的更多詳細信息:框架

Details

你甚至能夠編輯你新朋友的名字(或年齡,若是你是在扭曲事實):dom

Edit

你但願當你離開該應用而後返回時,你會被帶回到上一次查看的同一個毛茸茸朋友。但真的是這樣嗎?要知道答案的惟一方法就是測試它。

狀態恢復測試

運行應用,向右滑動至少一隻貓,查看你的匹配項,而後選擇一隻貓並查看他或她的詳細信息。按組合鍵 Cmd + Shift + H 返回主頁面。若是存在任何邏輯上的狀態,它都會被保存而且都將在此時運行。

接下來,經過 Xcode 中止應用:

Stop App

當用戶手動殺死應用或狀態恢復失敗時,狀態恢復框架將丟棄任何狀態信息。之因此存在這些檢查,以免你的應用不會陷入無線循環的錯誤狀態以及恢復崩潰。謝謝,Apple!:]

注意:你沒法經過應用切換器自行終止應用,不然狀態恢復將沒法正常工做。

再次啓動應用;你將回到主屏幕,而不是寵物詳情視圖。看起來你須要本身添加一些狀態恢復邏輯。

實現狀態恢復

設置狀態恢復的第一步是在你的應用代理中啓用它,打開 AppDelegate.swift 並添加如下代碼:

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

func application(application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
  return true
}
複製代碼

應用代理中有五個方法來管理狀態恢復。返回 trueapplication(_:shouldSaveApplicationState:),告訴系統保存 view 的狀態,並在應用處於後臺運行狀態時查看 view controller。返回 trueapplication(_:shouldRestoreApplicationState:),告訴系統在應用從新啓動時嘗試恢復原始狀態。

你能夠在某些狀況下讓這些代理方法返回 false,例如在測試時或用戶運行的應用的舊版本沒法恢復時。

構建並運行你的應用,而後導航到貓的詳情頁。按住組合鍵 Cmd + Shift + H 讓你的應用進入後臺,而後經過 Xcode 中止應用。你將看到如下內容:

Pet Finder

confused

與你以前看到的徹底相同!只選擇進行狀態恢復還不夠。雖然你已在應用中啓用了保存和恢復,但 view controller 還沒有參與。要解決這個問題,你須要爲每一個場景提供一個恢復標識符

設置恢復標識符

恢復標識符只是一個 view 和 view controller 的字符串屬性,UIKit 使用它來將這些對象恢復到以前的狀態。它存在一個 UIKit 與你但願保留的對象通信的值。只要這些屬性的值是惟一的,它們的實際內容並不重要。

打開 Main.storyboard,你將看到一個 tab bar controller、一個 navigation controller 和三個自定義 view controller:

cinder_storyboard

恢復標識符能夠在代碼中或在 Interface Builder 中設置。簡單起見,在本教程中你將在 Interface Builder 中進行設置。你能夠進入併爲每個 view controller 設置一個惟一的名稱,但 Interface Builder 有一個 Use Storyboard ID 的快捷選項,它容許你將 Storyboard ID 用於恢復標識符。

Main.storyboard 中,單擊 tab bar controller 並打開 Identity Inspector。啓用 Use Storyboard ID 選項,以下所示:

Use Storyboard ID

這樣會把 view controller 行存檔記錄,而且在狀態恢復過程當中進行還原。

對 navigation controller 和其它三個 view controller 重複此過程。確保你已經爲每一個 view controller 選中了 Use Storyboard ID。不然你的應用可能沒法正常恢復其狀態。

請注意,全部 controller 都已經具備 Storyboard ID,而且該複選框僅使用已做爲 Storyboard ID 的相同字符串。若是你未使用 Storyboard ID,你須要手動輸入一個惟一的 Storyboard ID

恢復標識符聚集在一塊兒,經過應用中任何 view controller 的惟一路徑造成恢復路徑;它與 API 中的 URI 相似,其中惟一路徑標識每一個資源的惟一路徑。

好比,如下路徑表明 MatchedPetsCollectionViewController

RootTabBarController/NavigationController/MatchedPetsCollectionViewController

經過這些設置,應用將記住你中止使用時的 view controller(大多數狀況下),而且任何 UIKit view 都將保留其先前的狀態。

構建並運行你的應用;返回寵物詳情頁測試恢復流程。暫停和恢復應用後,你應該看到如下內容:

No Data

雖然系統恢復了正確的 view controller,但它彷佛缺乏填充 view 所需的貓對象。如何恢復 view controller 及其所需的對象呢?

UIStateRestoring 協議

在實現狀態恢復方面,UIKit 爲你作了不少工做,可是你的應用須要負責自行處理一些事情:

  1. 告訴 UIKit 它想參與狀態恢復,就是你在應用代理中所作的那些。
  2. 告訴 UIKit 應該保留和恢復哪些 view controller 和 view。你經過爲 view controller 分配恢復標識符來解決此問題。
  3. 編碼和解碼任何須要重建 view controller 以前狀態的相關數據。你尚未這樣作,但這是 UIStateRestoring 協議須要解決的問題。

每一個具備恢復標識符的 view controller 都將在保存應用時接收 UIStateRestoring 協議對 encodeRestorableStateWithCoder(_:) 的調用。另外,view controller 將在應用恢復時接收 decodeRestorableStateWithCoder(_:) 的調用。

要完成恢復流程,你須要添加對 view controller 進行編碼和解碼的邏輯。雖然該過程多是最耗時的,但概念相對簡單。你一般會編寫一個擴展來增長協議的一致性,可是 UIKit 會自動關注冊 view controller 以符合 UIStateRestoring - 你只須要覆蓋適當的方法。

打開 PetDetailsViewController.swift,並在類的末尾添加如下代碼:

override func encodeRestorableStateWithCoder(coder: NSCoder) {
  //1
  if let petId = petId {
    coder.encodeInteger(petId, forKey: "petId")
  }

  //2
  super.encodeRestorableStateWithCoder(coder)
}
複製代碼

如下是上述代碼要作的事:

  1. 若是當前貓對象存在 ID,使用提供的編碼器進行保存以便稍後檢索。
  2. 確保調用 super 以便繼承的狀態恢復功能的其它部分可以按照預期發生。

經過少許的修改,如今你的應用能夠保存當前貓的信息。但請注意,你實際上並未保存貓的模型對象,而是稍後可用於獲取貓對象的 ID,當你保存經過 MatchedPetsCollectionViewController 選擇的貓時,可使用相同的概念。

Apple 很是清楚,狀態恢復用於存檔建立 view 層次結構所需並將應用恢復到其原始狀態的信息。每當應用進入後臺時,使用提供的編碼器來保存和恢復簡單模型數據是很誘人的,可是隻要狀態恢復失敗或用戶殺死應用,iOS 將會丟棄全部存檔數據。因爲你的用戶每次從新啓動應用時都不會很是樂意回到起始頁,因此最好遵循 Apple 的建議並僅使用此策略保存狀態恢復。

如今你已經在 PetDetailsViewController.swift 中實現了編碼,你能夠在下面添加相應的解碼方法:

override func decodeRestorableStateWithCoder(coder: NSCoder) {
  petId = coder.decodeIntegerForKey("petId")

  super.decodeRestorableStateWithCoder(coder)
}
複製代碼

解密 ID 並將其設置回 view controller 的 petId 屬性。

一旦解碼了 view controller 的對象,該 UIStateRestoring 協議就會提供 applicationFinishedRestoringState() 的其餘配置步驟。

PetDetailsViewController.swift 中添加如下代碼:

override func applicationFinishedRestoringState() {
  guard let petId = petId else { return }
  currentPet = MatchedPetsManager.sharedManager.petForId(petId)
}
複製代碼

上面是基於解碼後的寵物 ID 設置當前寵物,並完成 view controller 的恢復。固然,你能夠在 decodeRestorableStateWithCoder(_:) 執行此操做,但最好保持邏輯分離,由於當它們所有捆綁在一塊兒時它將變得笨拙。

構建並運行你的應用;導航到寵物的詳情頁並讓應用置於後臺,而後經過 Xcode 殺死該應用以觸發保存序列。重啓應用並驗證你的毛茸茸玩具是否按預期顯示:

Details

你已經學習瞭如何恢復經過 storyboard 建立的 view controller。但你在代碼中建立的 view controller 應該如何處理呢?要在運行時恢復基於 storyboard 建立的 view controller,UIKit 要作的是在 main storyboard 中找到它們。幸運的是,恢復基於代碼建立的 view controller 幾乎同樣容易。

恢復基於代碼建立的 view controller

視圖控制器 PetEditViewController 徹底由代碼建立;它用於編輯貓的名字和年齡。你將使用它來學習如何恢復基於代碼建立的 view controller。

構建並運行你的應用;導航到貓的詳情頁,而後點擊編輯。修改貓的名字,但不保存你的更改,以下所示:

Edit

如今將應用置於後臺並經過 Xcode 殺死它以觸發保存序列。重啓應用,iOS 將返回寵詳情頁而不是編輯頁:

Details

正如你在 Interface Builder 中構建的 view controller 所作的那樣,你須要爲 view controller 提供恢復 ID,並添加 UIStateRestoring 協議中的編碼和解碼方法以便正確恢復狀態。

查看 PetEditViewController.swift;你會注意到編碼和解碼的方法已經存在。邏輯相似於你在上一節中實現的編碼和解碼方法,但它還具備一些額外的屬性。

手動分配恢復標識符是一個簡單的過程。在 viewDidLoad() 中調用 super 後當即添加如下內容:

restorationIdentifier = "PetEditViewController"
複製代碼

這會爲 restorationIdentifier 視圖控制器分配惟一 ID。

在狀態恢復過程當中,UIKit 須要知道從何處得到 view controller 引用。在你設置 restorationIdentifier 的下面添加如下代碼:

restorationClass = PetEditViewController.self
複製代碼

這將設置 PetEditViewController 爲負責實例化 view controller 的恢復類。恢復類必須採用 UIViewControllerRestoration 協議並實現所需的恢復方法。爲此,將如下擴展代碼添加到 PetEditViewController.swift 的末尾:

extension PetEditViewController: UIViewControllerRestoration {
  static func viewControllerWithRestorationIdentifierPath(identifierComponents: [AnyObject], coder: NSCoder) -> UIViewController? {
    let vc = PetEditViewController()
    return vc
  }
}
複製代碼

這實現了返回類實例所需的 UIViewControllerRestoration 協議方法。如今 UIKit 有了它正在尋找的對象的副本,iOS 能夠調用編碼和解碼方法並恢復狀態。

構建並運行你的應用;導航到貓的編輯頁。像以前同樣更改貓的名字,但不保存更改,而後將應用置於後臺並經過 Xcode 將其刪除。重啓你的應用,並驗證你所作的全部工做,爲你的毛茸茸朋友提出一個偉大的獨特名稱並不是都是徒勞的!

Edit

接下來去哪兒?

你能夠 在此處如今已完成的項目。狀態恢復框架是任何 iOS 開發人員工具包中很是有用的工具;你如今能夠將基本恢復代碼添加到任何應用,並以此提升你的用戶體驗。

有關使用該框架可能實現的更多信息,請查看 2012 年2013 年的 WWDC 視頻。2013年的演示文稿特別有用,由於它涵蓋了 iOS 7 中引入的恢復概念,好比用於保存和恢復任意對象的 UIObjectRestoration 和在需求更復雜的應用中恢復表和集合視圖的 UIDataSourceModelAssociation

若是你對本教程有任何疑問或建議,請加入如下論壇討論!

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索