1:首先查看一下關於UIResponder的定義
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIResponder : NSObject //響應鏈中負責傳遞事件的方法 - (nullable UIResponder*)nextResponder; //一個響應對象成為第一響應者的一個前提是它可以成為第一響應者,可以用這個進行判斷,默認值為NO - (BOOL)canBecomeFirstResponder; //如果我們希望將一個響應對象作為第一響應者,則可以使用以下方法,如果對象成為第一響應者,則返回YES;否則返回NO - (BOOL)becomeFirstResponder; //是否可以辭去第一響應者,默認值為YES - (BOOL)canResignFirstResponder; //辭去第一響應者 - (BOOL)resignFirstResponder; //判定一個響應對象是否是第一響應者 - (BOOL)isFirstResponder; //響應觸摸事件 //手指按下的時候調用 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; //手指移動的時候調用 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; //手指抬起的時候調用 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; //取消(非正常離開屏幕,意外中斷) - (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; //響應移動事件 //移動事件開始 - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0); //移動事件結束 - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0); //移動事件取消 - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0); //響應遠程控制事件 - (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(4_0); //通過這個方法告訴UIMenuController它內部應該顯示什么內容,”復制”、”粘貼”等 - (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender NS_AVAILABLE_IOS(3_0); //默認的實現是調用canPerformAction:withSender:方法來確定對象是否可以調用action操作。如果我們想要重寫目標的選擇方式,則應該重寫這個方法。 - (nullable id)targetForAction:(SEL)action withSender:(nullable id)sender NS_AVAILABLE_IOS(7_0); //UIResponder提供了一個只讀方法來獲取響應鏈中共享的undo管理器,公共的事件撤銷管理者 @property(nullable, nonatomic,readonly) NSUndoManager *undoManager NS_AVAILABLE_IOS(3_0); @end
UIResponder提供了幾個方法來管理響應鏈,包括讓響應對象成為第一響應者、放棄第一響應者、檢測是否是第一響應者以及傳遞事件到下一響應者的方法;在UIKit中,UIApplication、UIView、UIViewController這幾個類都是直接繼承自UIResponder類。另外SpriteKit中的SKNode也是繼承自UIResponder類。因此UIKit中的視圖、控件、視圖控制器,以及我們自定義的視圖及視圖控制器都有響應事件的能力。
知識點1:事件分發制機hit-Testing;每當我們點擊了一下iOS設備的屏幕,UIKit就會生成一個事件對象UIEvent,然后會把這個Event分發給當前active的app;
告知當前活動的app有事件之后,UIApplication 單例就會從事件隊列中去取最新的事件,然后分發給能夠處理該事件的對象。這些事件按照先進先出的順序來處理。當處理事件時,程序的UIApplication對象會從隊列頭部取出一個事件對象,將其分發出去。UIApplication 獲取到Event之后,Application就糾結於到底要把這個事件傳遞給誰,這時候就要依靠HitTest來決定了。
iOS中,hit-Testing的作用就是找出這個觸摸點下面的View是什么,HitTest會檢測這個點擊的點是不是發生在這個View上,如果是的話,就會去遍歷這個View的subviews,直到找到最小的能夠處理事件的view,如果整了一圈沒找到能夠處理的view,則返回自身。
假設我們現在點擊到了圖中的E,hit-testing將進行如下步驟的檢測(不包含重寫hit-test並且返回非默認View的情況)
1、觸摸點在ViewA內,所以檢查ViewA的Subview B、C
2、觸摸點不在ViewB內,觸摸點在ViewC內部,所以檢查ViewC的Subview D、E
3、觸摸點不在ViewD內,觸摸點發生在ViewE內部,並且ViewE沒有subview,所以ViewE屬於ViewA中包含這個點的最小單位,所以ViewE變成了該次觸摸事件的hit-TestView
PS.
1、默認的hit-testing順序是按照UIView中Subviews的逆順序
2、如果View的同級別Subview中有重疊的部分,則優先檢查頂部的Subview,如果頂部的Subview返回nil, 再檢查底部的Subview
3、Hit-Test也是比較聰明的,檢測過程中有這么一點,就是說如果點擊沒有發生在某View中,那么該事件就不可能發生在View的Subview中,所以檢測過程中發現該事件不在ViewB內,也直接就不會檢測在不在ViewF內。也就是說,如果你的Subview設置了clipsToBounds=NO,實際顯示區域可能超出了superView的frame,你點擊超出的部分,是不會處理你的事件的,就是這么任性!
Hit-Test的檢查機制如上所示,當確定了Hit-TestView時,如果當前的application沒有忽略觸摸事件 (UIApplication:isIgnoringInteractionEvents),則application就會去分發事件(sendEvent:->keywindow:sendEvent:)
UIView中提供兩個方法用來確定hit-testing View,如下所示
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds
當一個View收到hitTest消息時,會調用自己的pointInside:withEvent:方法,如果pointInside返回YES,則表明觸摸事件發生在我自己內部,則會遍歷自己的所有Subview去尋找最小單位(沒有任何子view)的UIView,如果當前View.userInteractionEnabled = NO,enabled=NO(UIControl),或者alpha<=0.01, hidden等情況的時候,hitTest就不會調用自己的pointInside了,直接返回nil,然后系統就回去遍歷兄弟節點;
知識點2:事件傳遞;從上面我們可以知道關於事件的分發制機,並確定好處理事件的hit_text,接着就是處理事件的順序,正好跟事件分發制機相反,最有機會處理事件的對象是hit-test視圖或第一響應者。如果這兩者都不能處理事件,UIKit就會將事件傳遞到響應鏈中的下一個響應者。每一個響應者確定其是否要處理事件或者是通過nextResponder方法將其傳遞給下一個響應者。這一過程一直持續到找到能處理事件的響應者對象或者最終沒有找到響應者。
當系統檢測到一個事件時,將其傳遞給初始對象,這個對象通常是一個視圖。然后,會按以下路徑來處理事件(我們以上圖為例):
1.初始視圖(initial view)嘗試處理事件。如果它不能處理事件,則將事件傳遞給其父視圖。
2.初始視圖的父視圖(superview)嘗試處理事件。如果這個父視圖還不能處理事件,則繼續將視圖傳遞給上層視圖。
3.上層視圖(topmost view)會嘗試處理事件。如果這個上層視圖還是不能處理事件,則將事件傳遞給視圖所在的視圖控制器。
4.視圖控制器會嘗試處理事件。如果這個視圖控制器不能處理事件,則將事件傳遞給窗口(window)對象。
5.窗口(window)對象嘗試處理事件。如果不能處理,則將事件傳遞給單例app對象。
6.如果app對象不能處理事件,則丟棄這個事件。
從上面可以看到,視圖、視圖控制器、窗口對象和app對象都能處理事件。另外需要注意的是,手勢也會影響到事件的傳遞。
知識點3:響應鏈中負責傳遞事件的方法nextResponder;UIResponder類並不自動保存或設置下一個響應者,該方法的默認實現是返回nil。子類的實現必須重寫這個方法來設置下一響應者(如果要實現一個繼承於UIResponder,就要重寫給它設置一個下一個響應者是誰)。UIView的實現是返回管理它的UIViewController對象(如果它有)或者其父視圖。而UIViewController的實現是返回它的視圖的父視圖;UIWindow的實現是返回app對象;而UIApplication的實現是返回nil。所以,響應鏈是在構建視圖層次結構時生成的。
知識點4:辭去第一響應者resignFirstResponder,resignFirstResponder默認也是返回YES。需要注意的是,如果子類要重寫這個方法,則在我們的代碼中必須調用super的實現。
知識點5:默認情況下,多點觸摸是被禁用的。為了接受多點觸摸事件,我們需要設置響應視圖的multipleTouchEnabled屬性為YES。
知識點6:默認情況下,程序的每一個window都有一個undo管理器,它是一個用於管理undo和redo操作的共享對象。然而,響應鏈上的任何對象的類都可以有自定義undo管理器。例如,UITextField的實例的自定義管理器在文件輸入框放棄第一響應者狀態時會被清理掉。當需要一個undo管理器時,請求會沿着響應鏈傳遞,然后UIWindow對象會返回一個可用的實例。
知識點7:canPerformAction結合UIMenuController的運用
UIMenuController是UIKit里面的控件,UIMenuController的作用在開發中彈出的菜單欄,包含那些復制、粘貼等,也可以自定義要彈出的選擇及操作;UITextField、UIWebView、UITextView自帶有這種UIMenuController效果;
實例1:在Label中的運用,並且修改的UIMenuController選擇內容 #import "JHLabel.h" @implementation JHLabel /** 不管控件是通過xib stroyboard 還是純代碼 提供兩種初始化的操作都調用同一個方法 */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setupTap]; } return self; } /** 不管控件是通過xib stroyboard 還是純代碼 提供兩種初始化的操作都調用同一個方法 */ - (void)awakeFromNib { [self setupTap]; } /** 設置敲擊手勢 */ - (void)setupTap { self.text = @"author:會跳舞的獅子"; //已經在stroyboard設置了與用戶交互,也可以用純代碼設置 // self.userInteractionEnabled = YES; //當前控件是label 所以是給label添加敲擊手勢 [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]]; } /** 點擊label觸發的方法 */ - (void)labelClick { // 讓label成為第一響應者 \ 一定要寫這句話 因為這句話才是主動讓label成為第一響應者 [self becomeFirstResponder]; // 獲得菜單 UIMenuController *menu = [UIMenuController sharedMenuController]; // 設置菜單內容 \ 因為menuItems是數組 官方沒有給出需要傳入什么對象,但是以經驗可以判斷出需要傳入的是UIMenuItem對象 \ 而且顯示是按順序的 menu.menuItems = @[ [[UIMenuItem alloc] initWithTitle:@"頂" action:@selector(ding:)], [[UIMenuItem alloc] initWithTitle:@"回復" action:@selector(reply:)], [[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(warn:)] ]; // 菜單最終顯示的位置 \ 有兩種方式: 一種是以自身的bounds 還有一種是以父控件的frame [menu setTargetRect:self.bounds inView:self]; // [menu setTargetRect:self.frame inView:self.superview]; // 顯示菜單 [menu setMenuVisible:YES animated:YES]; } #pragma mark - UIMenuController相關 /** * 讓Label具備成為第一響應者的資格 */ - (BOOL)canBecomeFirstResponder { return YES; } /** * 通過第一響應者的這個方法告訴UIMenuController可以顯示什么內容 */ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持復制 || (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切 || action == @selector(paste:) || action == @selector(ding:) || action == @selector(reply:) || action == @selector(warn:)) return YES; return NO; } #pragma mark - 監聽MenuItem的點擊事件 /** 剪切 */ - (void)cut:(UIMenuController *)menu { //UIPasteboard 是可以在應用程序與應用程序之間共享的 \ (應用程序:你的app就是一個應用程序 比如你的QQ消息可以剪切到百度查找一樣) // 將label的文字存儲到粘貼板 [UIPasteboard generalPasteboard].string = self.text; // 清空文字 self.text = nil; } /** 賦值 */ - (void)copy:(UIMenuController *)menu { // 將label的文字存儲到粘貼板 [UIPasteboard generalPasteboard].string = self.text; } /** 粘貼 */ - (void)paste:(UIMenuController *)menu { // 將粘貼板的文字賦值給label self.text = [UIPasteboard generalPasteboard].string; } //如果方法不實現,是不會顯示出來的 - (void)ding:(UIMenuController *)menu { NSLog(@"%s %@", __func__, menu); } - (void)reply:(UIMenuController *)menu { NSLog(@"%s %@", __func__, menu); } - (void)warn:(UIMenuController *)menu { NSLog(@"%s %@", __func__, menu); } @end
知識點8:禁用一些長按的操作設置
代碼1:禁用所有長按文本框操作 #pragma mark - 禁用所有長按文本框操作 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if ([UIMenuController sharedMenuController]) { [UIMenuController sharedMenuController].menuVisible = NO; } return NO; }
代碼2:禁用部分長按文本框操作 #pragma mark - 禁用部分長按文本框操作 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { //禁用選擇、全選、粘貼功能 //... if (action == @selector(paste:)) return NO; if (action == @selector(select:)) return NO; if (action == @selector(selectAll:)) return NO; //... return [super canPerformAction:action withSender:sender]; }
實例: #import <UIKit/UIKit.h> @interface DDTextField : UITextField @end #import "DDTextField.h" @implementation DDTextField #pragma mark - - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(paste:)) return YES; if (action == @selector(cut:)) return YES; if (action == @selector(copy:)) return YES; if (action == @selector(select:)) return YES; if (action == @selector(selectAll:)) return YES; return NO; } @end
2:訪問快捷鍵命令
我們的應用可以支持外部設備,包括外部鍵盤。在使用外部鍵盤時,使用快捷鍵可以大大提高我們的輸入效率。因此從iOS7后,UIResponder類新增了一個只讀屬性keyCommands,來定義一個響應者支持的快捷鍵;
typedef NS_OPTIONS(NSInteger, UIKeyModifierFlags) { UIKeyModifierAlphaShift = 1 << 16, // Alppha+Shift鍵 UIKeyModifierShift = 1 << 17, //Shift鍵 UIKeyModifierControl = 1 << 18, //Control鍵 UIKeyModifierAlternate = 1 << 19, //Alt鍵 UIKeyModifierCommand = 1 << 20, //Command鍵 UIKeyModifierNumericPad = 1 << 21, //Num鍵 } NS_ENUM_AVAILABLE_IOS(7_0); //按鍵命令類: NS_CLASS_AVAILABLE_IOS(7_0) @interface UIKeyCommand : NSObject <NSCopying, NSSecureCoding> - (instancetype)init NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; //輸入字符串 @property (nonatomic,readonly) NSString *input; //按鍵調節器 @property (nonatomic,readonly) UIKeyModifierFlags modifierFlags; //按指定調節器鍵輸入字符串並設置事件 @property (nullable,nonatomic,copy) NSString *discoverabilityTitle NS_AVAILABLE_IOS(9_0); + (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action; // Key Commands with a discoverabilityTitle _will_ be discoverable in the UI. + (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action discoverabilityTitle:(NSString *)discoverabilityTitle NS_AVAILABLE_IOS(9_0); @end
知識點1:一個支持硬件鍵盤命令的響應者對象可以重新定義這個方法並使用它來返回一個其所支持快捷鍵對象(UIKeyCommand)的數組(在UIResponder (UIResponderKeyCommands)分類中)。每一個快捷鍵命令表示識別的鍵盤序列及響應者的操作方法。我們用這個方法返回的快捷鍵命令數組被用於整個響應鏈。當與快捷鍵命令對象匹配的快捷鍵被按下時,UIKit會沿着響應鏈查找實現了響應行為方法的對象。它調用找到的第一個對象的方法並停止事件的處理。
3:UIResponder (UIResponderKeyCommands)分類
//響應者類的按鍵命令類類目 @interface UIResponder (UIResponderKeyCommands) //組合快捷鍵命令(裝有多個按鍵的數組) @property (nullable,nonatomic,readonly) NSArray<UIKeyCommand *> *keyCommands NS_AVAILABLE_IOS(7_0); // returns an array of UIKeyCommand objects< @end @interface NSObject(UIResponderStandardEditActions) // these methods are not implemented in NSObject //剪貼 - (void)cut:(nullable id)sender NS_AVAILABLE_IOS(3_0); //復制 - (void)copy:(nullable id)sender NS_AVAILABLE_IOS(3_0); //粘貼 - (void)paste:(nullable id)sender NS_AVAILABLE_IOS(3_0); //選擇 - (void)select:(nullable id)sender NS_AVAILABLE_IOS(3_0); //選擇全部 - (void)selectAll:(nullable id)sender NS_AVAILABLE_IOS(3_0); //刪除 - (void)delete:(nullable id)sender NS_AVAILABLE_IOS(3_2); //從左到右寫入字符串(居左) - (void)makeTextWritingDirectionLeftToRight:(nullable id)sender NS_AVAILABLE_IOS(5_0); //從右到左寫入字符串(居右) - (void)makeTextWritingDirectionRightToLeft:(nullable id)sender NS_AVAILABLE_IOS(5_0); //切換字體為黑體(粗體) - (void)toggleBoldface:(nullable id)sender NS_AVAILABLE_IOS(6_0); //切換字體為斜體 - (void)toggleItalics:(nullable id)sender NS_AVAILABLE_IOS(6_0); //給文字添加下划線 - (void)toggleUnderline:(nullable id)sender NS_AVAILABLE_IOS(6_0); //增加字體大小 - (void)increaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0); //減小字體大小 - (void)decreaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0); @end
4:UIResponder (UIResponderInputViewAdditions)分類
@class UIInputViewController; @class UITextInputMode; @class UITextInputAssistantItem; @interface UIResponder (UIResponderInputViewAdditions) //鍵盤輸入視圖(系統默認的,可以自定義) @property (nullable, nonatomic, readonly, strong) __kindof UIView *inputView NS_AVAILABLE_IOS(3_2); //彈出鍵盤時附帶的視圖 @property (nullable, nonatomic, readonly, strong) __kindof UIView *inputAccessoryView NS_AVAILABLE_IOS(3_2); @property (nonnull, nonatomic, readonly, strong) UITextInputAssistantItem *inputAssistantItem NS_AVAILABLE_IOS(9_0) __WATCHOS_PROHIBITED; //鍵盤輸入視圖控制器 IOS8以后 @property (nullable, nonatomic, readonly, strong) UIInputViewController *inputViewController NS_AVAILABLE_IOS(8_0); //彈出鍵盤時附帶的視圖的視圖控制器 IOS8以后 @property (nullable, nonatomic, readonly, strong) UIInputViewController *inputAccessoryViewController NS_AVAILABLE_IOS(8_0); //文本輸入模式 @property (nullable, nonatomic, readonly, strong) UITextInputMode *textInputMode NS_AVAILABLE_IOS(7_0); //文本輸入模式標識 @property (nullable, nonatomic, readonly, strong) NSString *textInputContextIdentifier NS_AVAILABLE_IOS(7_0); //根據設置的標識清除指定的文本輸入模式 + (void)clearTextInputContextIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(7_0); //重新刷新鍵盤輸入視圖 - (void)reloadInputViews NS_AVAILABLE_IOS(3_2); @end
知識點1:UITextFields和UITextView有一個inputAccessoryView的屬性,當你想在鍵盤上展示一個自定義的view時,你就可以設置該屬性。你設置的view就會自動和鍵盤keyboard一起顯示了。
需要注意的是,你所自定義的view既不應該處在其他的視圖層里,也不應該成為其他視圖的子視圖。其實也就是說,你所自定義的view只需要賦給屬性inputAccessoryView就可以了,不要再做其他多余的操作。
我們在使用UITextView和UITextField的時候,可以通過它們的inputAccessoryView屬性給輸入時呼出的鍵盤加一個附屬視圖,通常是UIToolBar,用於回收鍵盤。
inputView就是顯示鍵盤的view,如果重寫這個view則不再彈出鍵盤,而是彈出自己的view.如果想實現當某一控件變為第一響應者時不彈出鍵盤而是彈出我們自定義的界面,那么我們就可以通過修改這個inputView來實現,比如彈出一個日期拾取器。
inputView不會隨着鍵盤出現而出現,設置了InputView只會當UITextField或者UITextView變為第一相應者時顯示出來,不會顯示鍵盤了。設置了InputAccessoryView,它會隨着鍵盤一起出現並且會顯示在鍵盤的頂端。InutAccessoryView默認為nil.
5:UIResponder (ActivityContinuation)分類
// 按鍵輸入箭頭指向 UIKIT_EXTERN NSString *const UIKeyInputUpArrow NS_AVAILABLE_IOS(7_0); UIKIT_EXTERN NSString *const UIKeyInputDownArrow NS_AVAILABLE_IOS(7_0); UIKIT_EXTERN NSString *const UIKeyInputLeftArrow NS_AVAILABLE_IOS(7_0); UIKIT_EXTERN NSString *const UIKeyInputRightArrow NS_AVAILABLE_IOS(7_0); UIKIT_EXTERN NSString *const UIKeyInputEscape NS_AVAILABLE_IOS(7_0); //響應者類的類目: @interface UIResponder (ActivityContinuation) //用戶活動 @property (nullable, nonatomic, strong) NSUserActivity *userActivity NS_AVAILABLE_IOS(8_0); //更新用戶活動 - (void)updateUserActivityState:(NSUserActivity *)activity NS_AVAILABLE_IOS(8_0); //恢復用戶活動 - (void)restoreUserActivityState:(NSUserActivity *)activity NS_AVAILABLE_IOS(8_0); @end
知識點1:支持User Activities,從iOS 8起,蘋果為我們提供了一個非常棒的功能,即Handoff。使用這一功能,我們可以在一部iOS設備的某個應用上開始做一件事,然后在另一台iOS設備上繼續做這件事。Handoff的基本思想是用戶在一個應用里所做的任何操作都可以看作是一個Activity,一個Activity可以和一個特定iCloud用戶的多台設備關聯起來。在編寫一個支持Handoff的應用時,會有以下三個交互事件:
- 為將在另一台設備上繼續做的事創建一個新的User Activity;
- 當需要時,用新的數據更新已有的User Activity;
- 把一個User Activity傳遞到另一台設備上。
為了支持這些交互事件,在iOS 8后,UIResponder類新增了幾個方法,我們在此不討論這幾個方法的實際使用,想了解更多的話,可以參考iOS 8 Handoff 開發指南。我們在此只是簡單描述一下這幾個方法。
在UIResponder中,已經為我們提供了一個userActivity屬性,它是一個NSUserActivity對象。因此我們在UIResponder的子類中不需要再去聲明一個userActivity屬性,直接使用它就行。其聲明如下:
@property(nonatomic, retain) NSUserActivity *userActivity
由UIKit管理的User Activities會在適當的時間自動保存。一般情況下,我們可以重寫UIResponder類的updateUserActivityState:方法來延遲添加表示User Activity的狀態數據。當我們不再需要一個User Activity時,我們可以設置userActivity屬性為nil。任何由UIKit管理的NSUserActivity對象,如果它沒有相關的響應者,則會自動失效。
另外,多個響應者可以共享一個NSUserActivity實例。
上面提到的updateUserActivityState:是用於更新給定的User Activity的狀態。其定義如下:
- (void)updateUserActivityState:(NSUserActivity *)activity
子類可以重寫這個方法來按照我們的需要更新給定的User Activity。我們需要使用NSUserActivity對象的addUserInfoEntriesFromDictionary:方法來添加表示用戶Activity的狀態。
在我們修改了User Activity的狀態后,如果想將其恢復到某個狀態,則可以使用以下方法:
- (void)restoreUserActivityState:(NSUserActivity *)activity
子類可以重寫這個方法來使用給定User Activity的恢復響應者的狀態。系統會在接收到數據時,將數據傳遞給application:continueUserActivity:restorationHandler:以做處理。我們重寫時應該使用存儲在user activity的userInfo字典中的狀態數據來恢復對象。當然,我們也可以直接調用這個方法。
最近有個妹子弄的一個關於擴大眼界跟內含的訂閱號,每天都會更新一些深度內容,在這里如果你感興趣也可以關注一下(嘿對美女跟知識感興趣),當然可以關注后輸入:github 會有我的微信號,如果有問題你也可以在那找到我;當然不感興趣無視此信息;