iOS开发事件分发机制—响应链—手势影响
1、提綱
- 什么是iOS的事件分發機制 ?
- 一個事件UIEvent又是如何響應的?
- 手勢對于響應鏈有何影響?
?
2、事件分發機制
2.1、來源
以直接觸摸事件為例:
如何找到處理這個事件的視圖的過程——事件分發機制
2.2、具體步驟
2.2.1、事件Event的產生
點擊一下iOS設備的屏幕,UIKit就會生成一個事件對象UIEvent,然后會把這個Event分發給當前活動的app;?
當前活動的app得知有事件,UIApplication 單例就會從事件隊列中去取最新的事件,然后分發給能夠處理該事件的對象(具體視圖)。
2.2.2、運用到的兩個UIView中的方法
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; //找到并返回最合適的視圖來 - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; //判斷點是否在視圖內當一個視圖View收到hitTest消息時,會調用自己的poinInside方法;
如果返回YES,View會遍歷自己的子視圖(遍歷順序先addSubView先遍歷),子視圖就會調用自己的hitTest方法;
如果返回NO,View就不會遍歷自己子視圖(很節約);
直到找到最小的能夠處理事件的view,如果整了一圈沒找到能夠處理的view,則返回自身。
2.2.3、舉例說明
白色:ViewController , 綠色:一個View視圖? , 藍色:一個Button按鈕
現象:點擊綠色視圖內的按鈕區域,正常;點擊綠色視圖外的按鈕區域,按鈕的selector方法不會調用?
重新綠色view的hitTest方法:
點擊有效區域時:返回視圖坐標{{88, -26}, {47, 52}},此坐標是相對父視圖的;
點擊區域外的部分時:返回視圖坐標{{0, 0}, {0, 0}},所以按鈕不會響應;
重新hitTest方法,修改返回view,當點擊區域外按鈕部分時也返回有效視圖{{88, -26}, {47, 52}},如圖所示;
另外一種解決方案:更暴力?
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{return YES; }號外:
如果 View 的 userInteractionEnabled = NO,enabled = NO( UIControl ),或者 alpha <= 0.01, hidden = YES 等情況的時候,直接返回 nil。如果觸摸點不在 view 中,直接返回 nil (例子就是此現象)。
3、響應鏈 響應鏈:在事件分發機制尋找view時會生成響應鏈; 第一響應者:上例中Button就是第一響應者; 下一個響應者:UIResponder有個屬性只讀的為nextResponder,當第一響應者不處理事件時就在吧事件拋給下一個響應者; 響應鏈的一些規則: 1. UIView 的 nextResponder 是直接管理它的 UIViewController (也就是 VC.view.nextResponder = VC ),如果當前 View 不是 ViewController 直接管理的 View,則 nextResponder 是它的 superView( view.nextResponder = view.superView )。 2. UIViewController 的 nextResponder 是它直接管理的 View 的 superView( VC.nextResponder = VC.view.superView )。 如果viewcontroller的view是window的根view,那么下一個響應者是window; 如果viewcontroller是另一個viewcontroller模態推出的,那么下一個響應者是另一個viewcontroller; 如果viewcontroller的view被add到另一個viewcontroller的根view上,那么下一個響應者是另一個viewcontroller的根view 3. UIWindow 的 nextResponder 是 UIApplication 。 4. UIApplication 的 nextResponder 是 AppDelegate。 上例中的響應鏈:UIButton.nextResponder = 綠色view.nextResponder = VC.view.nextResponder = VC.nextResponder = VC.view.superViewe(本例中為UIWindow).nextResponder = UIApplication.nextResponder = AppDelegate ;
? 一般來說,某個 UIResponder 的子類想要自己處理一些事件,就需要重寫它的這些方法(觸摸為例):
- (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:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);如果想自己處理后,繼續讓事件響應下去:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[super touchesBegan:touches withEvent:event]; }- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[super touchesBegan:touches withEvent:event]; }- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[super touchesBegan:touches withEvent:event]; }- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[super touchesBegan:touches withEvent:event]; }?
4、手勢對響應鏈有何影響
手勢識別器并不是響應者鏈中的一員,但是手勢識別器會觀察touch事件,并延遲事件向所綁定的視圖傳遞;
在上例中給Button和view添加點擊手勢:
按鈕會優先響應手勢,而不是自身的selector;
設置手勢代理:讓按鈕響應自身的selector - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{if ([touch.view isKindOfClass:[UIButton class]]) {return NO;}else{return YES;} }
添加手勢又屏蔽:有毛病?
在其他UICollectionView和UIScrollView、UITableView等,如果需要在視圖上添加手勢,cell上也會響應手勢,此方法可以解決手勢和自身方法的沖突!
?
?
轉載于:https://www.cnblogs.com/xianfeng-zhang/p/9473063.html
總結
以上是生活随笔為你收集整理的iOS开发事件分发机制—响应链—手势影响的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】从0开始写爬虫——扒狗东
- 下一篇: jenkins简单部署