先總說如下:
1、當手指觸摸到屏幕時,會產生UITouch對象和UIEvent對象。
2、這兩個對象產生后會被傳遞到UIApplication管理的一個事件隊列中。
3、再有UIApplication會在事件隊列中去除排在最前面的事件(有先后順序),將事件傳遞到程序的(keyWindow)。
4、主窗口在視圖層找到合適的視圖來處理觸摸事件。
5、找到合適的視圖控件后就會調用控件的Touch方法。
下面詳細介紹每一步:
1、當手指觸摸到屏幕時,會產生UITouch對象和UIEvent對象
觸摸時間發生時就長生了UITouch和UIEvent對象(UITouch早於UIEvent產生)。UITouch對象和點擊事件一一對應,一根手指對應一個UITouch對象(默認一個控件只有一個UITouch對象)。
UITouch對象保存着觸摸事件的觸摸位置、時間、階段。且當手指移動時,UITouch對象會隨着手指的移動不斷更新。當手指離開屏幕時,該對象被系統銷毀。
UITouch包含的屬性:
//觸摸產生時所處的窗口 @property(nonatomic,readonly,retain) UIWindow *window; //觸摸產生時所處的視圖 @property(nonatomic,readonly,retain) UIView *view; //短時間內點按屏幕的次數 (可據此判斷單擊、雙擊或更多的點擊) @property(nonatomic,readonly) NSUInteger tapCount; //記錄了觸摸事件產生或變化時的時間,單位是秒 @property(nonatomic,readonly) NSTimeInterval timestamp; //當前觸摸事件所處的狀態 @property(nonatomic,readonly) UITouchPhase phase;
UITouch涉及的方法
- (CGPoint)locationInView:(UIView *)view;
- 返回值表示觸摸在view上的位置
- 這里返回的位置是針對view的坐標系的(以view的左上角為原點(0, 0))
- 調用時傳入的view參數為nil的話,返回的是觸摸點在UIWindow的位置
- (CGPoint)previousLocationInView:(UIView *)view;
- 該方法記錄了前一個觸摸點的位置
UIEvent就是觸摸事件的事件對象,記錄事件的產生時間和事件類型(iOS中事件類型包括:觸摸事件、加速事件、遙控事件);
UIEvent包含的屬性
//事件類型 @property(nonatomic,readonly) UIEventType type; //事件類型 (分的比上一個較細,用的很少) @property(nonatomic,readonly) UIEventSubtype subtype; //事件產生的時間 @property(nonatomic,readonly) NSTimeInterval timestamp;
2、這兩個對象產生后會被傳遞到UIApplication管理的一個事件隊列中
3、再有UIApplication會在事件隊列中去除排在最前面的事件(有先后順序),將事件傳遞到程序的(keyWindow)(這兩部分沒什么值得說的!!!忽略吧!)
4、主窗口在視圖層找到合適的視圖來處理觸摸事件
觸摸事件的傳遞准尋得准則是從父控件傳遞到子控件的傳遞。
如何找到合適的控件來處理事件呢?
准尋得原則是從UIApplication -> UIWindow->父控件->子控件。同一級的控件先判斷在上面的(后創建的)。
事件到達每一級都要先判斷該級本身是否可以處理觸摸事件(能交互、不隱藏、不透明即可),再判斷觸摸點是否在自己身上。然后再往后遍歷子控件重復前面的步驟。如果沒有符合條件的子控件就有該控件處理。
找最合適的處理控件用到
-(UIView)hitTest:(CGPoint)point withEvent:(UIEvent *)event
判斷點是否在空間上用到
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
5、找到合適的視圖控件后就會調用控件的Touch方法
一次完整的觸摸過程,會經歷3個狀態:
//觸摸開始 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event //觸摸移動 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event //觸摸結束 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event //觸摸取消(可能會經歷)(這是突發事件時的處理) - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
這些touches方法的默認做法是將事件順着響應者鏈條向上傳遞,將事件交給上一個響應者進行處理。
響應者鏈的事件傳遞過程:
a、如果view的控制器存在,就傳遞給控制器;如果控制器不存在,則將其傳遞給它的父視圖
b、在視圖層次結構的最頂級視圖,如果也不能處理收到的事件或消息,則其將事件或消息傳遞給window對象進行處理
c、如果window對象也不處理,則其將事件或消息傳遞給UIApplication對象
d、如果UIApplication也不能處理該事件或消息,則將其丟棄
