級別: ★★☆☆☆
標簽:「iOS」「UIStateRestoration」
作者: 沐靈洛
審校: QiShare團隊
前言:iOS 開發(fā)中,我們都知道一個App點擊了home按鍵或者切換至其他應用時,將進入后臺。隨著時間的推移资柔,App會經歷后臺運行,后臺懸掛撵割,最后被殺死贿堰。假如有這樣一個場景:
場景1:用戶正在使用我們App進行個人信息的編輯,突然接到了一個電話啡彬,使得App進入后臺并且通話時間超過了App后臺备耄活的時間。當用戶通話完畢的時候庶灿,返回繼續(xù)填寫纵搁,卻發(fā)現App重新啟動了,并且用戶之前填寫的數據往踢,都沒有保存腾誉,需要重新輸入?用戶的體驗會很不好峻呕。
對于此問題利职,我們可能會說讓App后臺保持活躍不就行啦。是的山上,這是個很好的解決方案眼耀。但是除了這個方案,我們是不是有其他的辦法實現UI界面和數據的保存和恢復佩憾。答案是肯定的哮伟,接下來我們會介紹一種方案UIStateRestoration
。
一妄帘、關于UIStateRestoration
UIStateRestoration出現于iOS 6.0以后的API中楞黄。主要幫助我們實現特定場景下的UI保存和恢復。UIStateRestoration是一個協(xié)議類抡驼,在蘋果的系統(tǒng)中UIKit框架下的UIApplication鬼廓、UIViewController、UIView都實現了UIStateRestoration協(xié)議致盟。
關于UI狀態(tài)從應用程序啟動到恢復以及UI狀態(tài)保存時相關API的調用順序碎税,用官網的圖解大家可以理解的更清楚尤慰。
UI狀態(tài)恢復,只有當AppDelegate實現application:shouldRestoreApplicationState:
并且在方法中返回true時才會生效雷蹂。
UI狀態(tài)保存伟端,只有當AppDelegate實現application: shouldSaveApplicationState:
并且在方法中返回true時才會生效。
二匪煌、UIStateRestoration的介紹
- 系統(tǒng)進行UI狀態(tài)的保存和恢復時责蝠,自動使用以下常量字符串,進行相關數據的歸檔萎庭。
#pragma mark -- State Restoration Coder Keys --
// UIStoryBoard that originally created the ViewController that saved state, nil if no UIStoryboard
//保存和創(chuàng)建一個故事版用到的key
UIKIT_EXTERN NSString *const UIStateRestorationViewControllerStoryboardKey NS_AVAILABLE_IOS(6_0);
// NSString with value of info.plist's Bundle Version (app version) when state was last saved for the app
//應用程序上次狀態(tài)保存時info.plist的應用程序版本
UIKIT_EXTERN NSString *const UIApplicationStateRestorationBundleVersionKey NS_AVAILABLE_IOS(6_0);
// NSNumber containing the UIUserInterfaceIdiom enum value of the app that saved state
//狀態(tài)保存時應用程序的`UIUserInterfaceIdiom`枚舉值
UIKIT_EXTERN NSString *const UIApplicationStateRestorationUserInterfaceIdiomKey NS_AVAILABLE_IOS(6_0);
// NSDate specifying the date/time the state restoration archive was saved. This is in UTC.
//狀態(tài)保存的時間霜医,UTC格式。
UIKIT_EXTERN NSString *const UIApplicationStateRestorationTimestampKey NS_AVAILABLE_IOS(7_0);
// NSString with value of the system version (iOS version) when state was last saved for the app
//上次應用程序保存狀態(tài)時的系統(tǒng)版本(iOS版本)
UIKIT_EXTERN NSString *const UIApplicationStateRestorationSystemVersionKey NS_AVAILABLE_IOS(7_0);
- UIViewControllerRestoration協(xié)議:在UI狀態(tài)恢復時幫我們生成一個控制器驳规。
#pragma mark -- State Restoration protocols for UIView and UIViewController --
// A class must implement this protocol if it is specified as the restoration class of a UIViewController.
//如果將類指定為UIViewController的恢復類肴敛,則必須實現此協(xié)議。
@protocol UIViewControllerRestoration
+ (nullable UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder;
@end
- UIDataSourceModelAssociation協(xié)議:目前只有UITableView and UICollectionView實現了這個協(xié)議达舒。
官網說明: UIDataSourceModelAssociation.
@protocol UIDataSourceModelAssociation
- (nullable NSString *) modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view;
- (nullable NSIndexPath *) indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view;
@end
- UIStateRestoring協(xié)議:實現UIStateRestoring協(xié)議值朋,可以讓我們自定義的視圖(非UIView和UIViewController子類)加入狀態(tài)恢復。前提必須使用UIApplication的
+ (void)registerObjectForStateRestoration:(id<UIStateRestoring>)object restorationIdentifier:(NSString *)restorationIdentifier
方法注冊巩搏。
+ (void)registerObjectForStateRestoration:(id<UIStateRestoring>)object restorationIdentifier:(NSString *)restorationIdentifier
@protocol UIObjectRestoration;
// Conform to this protocol if you want your objects to participate in state restoration.
// To participate in state restoration, the function registerObjectForStateRestoration must
// be called for the object.
/*如果您希望對象參與狀態(tài)恢復,請遵守此協(xié)議趾代。
要參與狀態(tài)恢復贯底,函數registerObjectForStateRestoration必須為此對象而調用。*/
@protocol UIStateRestoring <NSObject>
@optional
// The parent property is used to scope the restoration identifier path for an object, to
// disambiguate it from other objects that might be using the same identifier. The parent
// must be a restorable object or a view controller, else it will be ignored.
/*parent屬性用于定義一個對象的恢復標識恢復路徑撒强,以便從可能使用相同恢復標識的其他對象中消除歧義禽捆。
parent屬性必須是可恢復對象`id<UIStateRestoring> `或視圖控制器,否則將被忽略飘哨。
個人理解:類似繼承體系模式胚想,方便歸整清楚恢復的路徑,幫助我們進行一定順序和層次的恢復芽隆。*/
@property (nonatomic, readonly, nullable) id<UIStateRestoring> restorationParent;
// The restoration class specifies a class which is consulted during restoration to find/create
// the object, rather than trying to look it up implicitly
/*
objectRestorationClass指定在恢復期間用于查找和創(chuàng)建需要恢復的對象的類浊服。
并不是試圖隱式查找和創(chuàng)建需要恢復的對象
*/
@property (nonatomic, readonly, nullable) Class<UIObjectRestoration> objectRestorationClass;
// Methods to save and restore state for the object. If these aren't implemented, the object
// can still be referenced by other objects in state restoration archives, but it won't
// save/restore any state of its own.
/*
保存和恢復對象狀態(tài)的方法。
如果沒有實現這些方法胚吁,對象仍可以被狀態(tài)恢復歸檔中的其他對象引用牙躺,但它將不會保存和恢復自己的任何狀態(tài)。
*/
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder;
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder;
// applicationFinishedRestoringState is called on all restored objects that implement the method *after* all other object
// decoding has been done (including the application delegate). This allows an object to complete setup after state
// restoration, knowing that all objects from the restoration archive have decoded their state.
/*在所有其他對象實現恢復方法腕扶,解碼完成(包括`AppDelegate`的解碼)并恢復了所有的可恢復對象后才會調用applicationFinishedRestoringState孽拷。
這允許對象在狀態(tài)恢復之后完成設置,可以通過此方法明確知道恢復檔案中的所有對象都已解碼其狀態(tài)
*/
- (void) applicationFinishedRestoringState;
@end
// Protocol for classes that act as a factory to find a restorable object during state restoration
// A class must implement this protocol if it is specified as the restoration class of a UIRestorableObject.
//作為工廠類的協(xié)議半抱,用于在狀態(tài)恢復期間查找可恢復對象脓恕。如果指定某個類為`id<UIStateRestoring>`的`objectRestorationClass `膜宋,則該類必須實現此協(xié)議。
@protocol UIObjectRestoration
+ (nullable id<UIStateRestoring>) objectWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder;
@end
UIStateRestoration場景
適用于App進入后臺炼幔,后臺停留時間超過系統(tǒng)分配的后臺活躍時間后被系統(tǒng)殺死時的場景秋茫。因為當用戶強制退出應用程序時,系統(tǒng)會自動刪除應用程序的保留狀態(tài)江掩。在應用程序被終止時刪除保留的狀態(tài)信息是一項安全預防措施学辱。如果應用程序在啟動時崩潰,系統(tǒng)也會刪除保留狀態(tài)作為類似的安全預防措施环形。
UIStateRestoration調試
根據場景描述策泣,如果要測試應用程序恢復其狀態(tài)的能力,則在調試期間不應使用多任務欄來強制終止應用程序抬吟∪荆可以通過設置項目的plist文件下
Application does not run in background
為YES。
UIApplication對于UIStateRestoration協(xié)議的實現接口
#pragma mark -- State Restoration protocol adopted by UIApplication delegate --
- (nullable UIViewController *) application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
UIViewController對于UIStateRestoration協(xié)議的實現接口
@interface UIViewController (UIStateRestoration) <UIStateRestoring>
@property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
@property (nullable, nonatomic, readwrite, assign) Class<UIViewControllerRestoration> restorationClass NS_AVAILABLE_IOS(6_0);
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) applicationFinishedRestoringState NS_AVAILABLE_IOS(7_0);
@end
UIView對于UIStateRestoration協(xié)議的實現接口
@interface UIView (UIStateRestoration)
@property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
@end
本篇我們介紹了UI狀態(tài)保存和恢復的流程火本,UIStateRestoration
協(xié)議類的方法危队,適用場景,調試策略以及UIApplication钙畔、UIViewController茫陆、UIView關于1UIStateRestoration1協(xié)議所提供的接口方法。
下篇文章我們將介紹如何實現UI狀態(tài)保存和恢復擎析。
推薦文章:
Swift 運算符
iOS 中精確定時的常用方法
Sign In With Apple(一)
算法小專欄:動態(tài)規(guī)劃(一)
Dart基礎(一)
Dart基礎(二)
Dart基礎(三)
Dart基礎(四)
iOS 短信驗證碼倒計時按鈕