iOS 事件傳遞(Touch事件)


先總說如下:

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也不能處理該事件或消息,則將其丟棄

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM