iOS事件的傳遞和響應機制
原始碼下載
iOS事件分類
1.Touch Events(觸控事件)
2.Motion Events(運動事件)
3.Remote Events (遠端事件)
4.Press Events(按壓事件)
事件處理週期:
1.事件產生和傳遞
2.找到合適的view處理
3.處理事件或者捨棄
這裡主要是說觸控事件。
響應者物件:可以處理事件的物件,即UIResponder的子類物件。
事件響應鏈:通過UIResponder的屬性串連在一起的一條虛擬的鏈,用來對App事件進行處理。
- (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event; //手指在螢幕上移動或按壓
- (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event; //手指離開螢幕
- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event; //觸控被中斷,例如觸控時電話呼入
如果iOS要對事件進行響應,則這個物件必須繼承了UIResponder的物件。就算是繼承了UIResponder也有情況不能進行事件響應。
不能響應iOS事件的物件:
1.不是UIResponder的子類。
2.控制元件的userInteractionEnabled屬性為NO。
3.控制元件被隱藏了(父控制元件被隱藏,所有的子控制元件也被隱藏)。
4.透明對低於0.01。
響應事件在響應者鏈中的傳遞過程。
1 事件產生之後,會被加入到UIApplication管理的時間佇列裡,接下來就自UIApplication向下傳遞,首先傳給主window,window傳給根view,然後按照view的層級一層一層的傳遞一直到找到最合適的view來處理事件。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)
pointInside:withEvent:方法作用是判斷點是否在檢視內,是則返回YES,否則返回NO
2 根據響應者的判斷,如果當前視窗不是合適的響應者,則會把訊息傳遞給響應鏈中的下一個響應者。
下一個響應者的判斷原則
UIView
如果當前的view為控制器的根view,那麼控制器就是下一個響應者。如果當前view不是控制器的view,則這個view的父控制元件就是下一個響應者。
UIViewController
如果viewcontroller的view是window的根view,那麼下一個響應者就是window,如果viewcontroller是模態出來的,下一個響應者就是模態出這個viewcontroller的viewController,如果viewcontroller的view是被add到另外一個Controller的根view上,那麼下一個響應者就是viewcontroller的根view。
UIWindow
UIWindow的下一個響應者是UIApplication
UIApplication
通常UIApplication是響應者鏈的最頂端(如果app delegate也是UIRespoonder的子類物件,那麼事件還會傳給app delegate)
3.如果再檢視層次結構的最頂層還是不能處理事件或者訊息就把事件傳遞給window物件進行處理。
4.如果window物件也不處理,就把物件交給UIApplication物件。
5.如果UIApplication物件也不處理就丟棄。
響應者鏈的程式碼
UIResponder * next = [self nextResponder];
NSMutableString * prefix = @"".mutableCopy;
while (next != nil) {
NSLog(@"%@%@", prefix, [next class]);
[prefix appendString: @"--"];
next = [next nextResponder];
}
原始碼
MyTouchView.h
//
// MyTouchView.h
// ShiJianDemo
//
// Created by liuyinghui on 2018/3/5.
// Copyright © 2018年 liuyinghui. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface MyTouchView : UIView
@end
MyTouchView.m
//
// MyTouchView.m
// ShiJianDemo
//
// Created by liuyinghui on 2018/3/5.
// Copyright © 2018年 liuyinghui. All rights reserved.
//
#import "MyTouchView.h"
@implementation MyTouchView
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event{
NSLog(@"%@",self);
return [super hitTest:point withEvent:event];
} // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
@end