UIKit可識別三種類型的輸入事件:程序員
觸摸事件app
運動(加速計)事件ide
遠程控制事件函數
iOS中許多事件對象都是UIEvent類的實例,記錄事件產生的時刻和類型性能
UIEvent類事件類型的enum常量:spa
typedef NS_ENUM(NSInteger, UIEventType) {對象
UIEventTypeTouches,繼承
UIEventTypeMotion,遞歸
UIEventTypeRemoteControl,隊列
};
由UIEvent對象的type屬性能夠獲取事件的類型
在iOS中不是任何對象都能處理事件,只有繼承了UIResponder的對象才能接收並處理事件。咱們稱之爲「響應者對象」
UIApplication、UIViewController、UIView都繼承自UIResponder,所以它們都是響應者對象,都可以接收並處理事件
UIView是UIResponder的子類,能夠覆蓋下列4個方法處理不一樣的觸摸事件。
1. 一根或者多根手指開始觸摸屏幕
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2.一根或者多根手指在屏幕上移動(隨着手指的移動,會持續調用該方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
3.一根或者多根手指離開屏幕
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
4.觸摸結束前,某個系統事件(例如電話呼入)會打斷觸摸過程
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
注意:全部UIKit控件均繼承自UIView
上述4個方法都有個UIEvent的參數,經過UIEvent能夠獲得事件的類型和產生時間,以及當前處於活動狀態的全部觸摸操做。可是,一般會使用UITouch對象而不是UIEvent對象來處理觸摸事件
當用戶觸摸屏幕時,系統會建立一個UITouch實例,並將該對象和接觸屏幕的那根手指關聯。UITouch保存着手指在屏幕上觸摸的位置。當手指移動時,系統會更新同一個UITouch對象,使之可以一直保存該手指在屏幕上的當前位置。當手指離開屏幕時,系統會取消相應的UITouch對象
UITouch對象還會保存一些其餘信息,好比,手指的前一個位置、手指按下屏幕的次數(tapCount, 能夠用來判斷單擊和雙擊事件)
提示:iPhone開發中,要避免使用雙擊事件!
window:觸摸產生時所處的窗口。因爲窗口可能發生變化,當前所在的窗口不必定是最開始的窗口
view:觸摸產生時所處的視圖。因爲視圖可能發生變化,當前視圖也不必定時最初的視圖
tapCount:點按操做和鼠標的單擊操做相似,tapCount表示短期內點按屏幕的次數。所以能夠根據tapCount判斷單擊、雙擊或更多的點按
timestamp:時間戳記錄了觸摸事件產生或變化時的時間,單位是秒
phase:觸摸事件在屏幕上有一個週期,即觸摸開始、觸摸點移動、觸摸結束,還有中途取消。經過phase能夠查看當前觸摸事件在一個週期中所處的狀態。phase是UITouchPhase類型的,是一個枚舉配型,包含:
UITouchPhaseBegan(觸摸開始)
UITouchPhaseMoved(接觸點移動)
UITouchPhaseStationary(接觸點無移動)
UITouchPhaseEnded(觸摸結束)
UITouchPhaseCancelled(觸摸取消)
- (CGPoint)locationInView:(UIView *)view:
返回一個CGPoint類型的值,表示觸摸在view這個視圖上的位置,這裏返回的位置是針對view的座標系的。調用時傳入的view參數爲空的話,返回的時觸摸點在整個窗口的位置
- (CGPoint)previousLocationInView:(UIView *)view:
該方法記錄了前一個座標值,函數返回也是一個CGPoint類型的值, 表示觸摸在view這個視圖上的位置,這裏返回的位置是針對view的座標系的。調用時傳入的view參數爲空的話,返回的時觸摸點在整個窗口的位置
當某個UIView發生觸摸事件時,系統會將和事件相關的UITouch對象做爲參數傳入
由於能夠有多根手指同時觸發同一個事件,因此傳給視圖的是一組UITouch對象,保存在NSSet中,例如:
若是兩根手指同時觸摸某個視圖,那麼touchesBegan:withEvent:的第一個參數是包含兩個UITouch實例的NSSet對象
若是這兩根手指一前一後分開觸摸同一個視圖,那麼視圖會收到兩個獨立的touchesBegan:withEvent:消息,而且每一個NSSet對象中只包含一個UITouch對象
所以,根據NSSet中UITouch的個數能夠判斷出是單點觸摸仍是多點觸摸
發生觸摸事件後,系統會將該事件加入到一個由UIApplication管理的事件隊列中
UIApplication會從事件隊列中取出最前面的事件並將其分發以便處理,一般,先發送事件給應用程序的主窗口
主窗口會調用hitTest:withEvent:方法在視圖繼承樹中找到一個最合適的子視圖來處理觸摸事件,該子視圖即爲hit-test視圖
若是hit-test視圖不處理收到的事件消息,UIKit則將事件轉發到響應者鏈中的下一個響應者,看其是否能對該消息進行處理
響應者鏈條,是經過遞歸構成的一組UIResponder對象的鏈式序列!
若是hit-test視圖沒法處理事件,則經過響應者鏈向上傳遞
若是hit-test視圖的控制器存在,就傳遞給控制器;若是控制器不存在,則將其傳遞給它的父視圖
若是視圖或它的控制器沒法處理收到的事件或消息,則將其傳遞給該視圖的父視圖
每個在視圖繼承樹中的上層視圖若是不能處理收到的事件或消息,則重複上面的步驟
在視圖層次結構的最頂級視圖,若是也不能處理收到的事件或消息,則其將事件或消息傳遞給window對象進行處理
若是window對象也不處理,則其將事件或消息傳遞給UIApplication對象
若是UIApplication也不能處理該事件或消息,則將其丟棄
不接收用戶交互:
userInteractionEnabled = NO;
隱藏:
hidden = YES;
透明:
alpha = 0~0.01
四個UITouch事件:
1. 一根或者多根手指開始觸摸屏幕
- (void)touchesBegan:withEvent:
2.一根或者多根手指在屏幕上移動
- (void)touchesMoved:withEvent:
3.一根或者多根手指離開屏幕
- (void)touchesEnded:withEvent:
4.觸摸結束前,某些系統事件會打斷觸摸過程
- (void)touchesCancelled:withEvent:
按照響應者鏈順序遞歸查找最早處理事件的UIView,重寫hitTest:withEvent:方法能夠攔截觸摸事件
觸摸事件處理簡單觸摸很是容易,可是要處理複雜的手勢就會變得比較很是困難。爲了解決這一問題,蘋果推出了手勢識別,在簡化手勢處理的同時,還有效地統一了用戶使用習慣
iOS3.2版本以後,蘋果推出了手勢識別(Gesture Recognizer),其目的是:
簡化開發者的開發難度
統一用戶體驗
iOS目前支持的手勢識別
UITapGestureRecognizer(點按)
UIPinchGestureRecognizer(捏合)
UIPanGestureRecognizer(拖動)
UISwipeGestureRecognizer(輕掃)
UIRotationGestureRecognizer(旋轉)
UILongPressGestureRecognizer(長按)
提示:目前遊戲中的手勢識別使用的很少
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
// 沒有觸摸事件發生,全部手勢識別的默認狀態
UIGestureRecognizerStatePossible,
// 一個手勢已經開始但還沒有改變或者完成時
UIGestureRecognizerStateBegan,
// 手勢狀態改變
UIGestureRecognizerStateChanged,
// 手勢完成
UIGestureRecognizerStateEnded,
// 手勢取消,恢復至Possible狀態
UIGestureRecognizerStateCancelled,
// 手勢失敗,恢復至Possible狀態
UIGestureRecognizerStateFailed,
// 識別到手勢識別
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
};
提示:UITapGestureRecognizer也被稱爲離散手勢,該手勢識別不會被取消,只是調用一次selector任務
建立手勢識別實例
設置手勢識別屬性,例如手指數量,方向等
將手勢識別附加到指定的視圖之上
編寫手勢觸發監聽方法
state——手勢狀態
view——手勢發生視圖
經常使用方法
locationInView 得到手勢發生對應視圖所在位置
translationInView 相對於起始位置在視圖中的平移位置
重寫canBecomeFirstResponder方法返回YES,容許視圖控制器成爲第一響應者
在viewDidAppear方法中將視圖控制器設置爲第一響應者
在viewDidDisappear方法中註銷視圖控制器第一響應者的身份
監聽並處理運動事件監聽方法
觸摸事件的類型一共有四個,一次完整的觸摸,至少包括開始和結束兩個事件
1> 觸摸開始,用手指(一根或者多根)按在屏幕上
2> 觸摸移動,手指在屏幕上發生移動(有可能會發生)
3> 觸摸結束,手指從屏幕上離開
4> 觸摸被取消,由於系統事件(例如電話呼叫)一次觸摸事件被取消
觸摸對象UITouch的屬性及方法
屬性:
1> view: 檢測到觸摸事件的視圖,在開發中使用最爲頻繁的屬性
2> window: 窗口,發生觸摸事件的窗口
3> phase: 相位屬性,開發中極少使用,通常用戶自定義手勢識別
4> timestamp: 發生觸摸的時間
以上兩個屬性,一般用戶開發自定義手勢識別,平常開發中不須要使用。
5> tapCount: 發生觸摸時,在短期內,手指點按的次數,一般用於判斷單擊仍是雙擊
提示:在iOS開發中,儘可能少用雙擊事件!
若是要使用雙擊,須要有圖形化的界面提示用戶,某一個控件上是容許雙擊操做的。
方法:
1> locationInView: 發生觸摸事件相對視圖的位置(座標點)
2> previousLocationInView: 發生觸摸事件前一次手指所在的位置(座標點)
對於單點觸摸,常用
UITouch *touch = [touches anyObject];
從touches集合中獲取到用戶的觸摸對象
一般,在應用程序開發中,爲了簡化程序的複雜度,通常只是用單點觸摸,
而若是須要支持多點觸摸,一般是使用手勢識別來處理。
1. 若是是一根手指,在屏幕上繪製藍色的圖像
2. 若是是多根手指,一根手指是藍色的圖像,另一根是紅色圖像
1> 在touchesMoved方法中,touches集合中的UITouch對象的順序不會發生改變
2> 在使用塊代碼時,其中的代碼只是預先準備好的一個程序塊,在須要時會被調用
用於檢測具體響應用戶觸摸點視圖的方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
與
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
在視圖內部返回YES,不然返回NO
聯合使用來判斷用戶觸摸點的位置是否在指定的視圖內部,若是是,表示該視圖能夠接收用戶交互。
以上兩個方法會被循環遞歸,屢次調用!直至找到最適合響應用戶請求的視圖!
提示:通常狀況下,不要輕易重寫這兩個方法,由於一旦方法內部使用了消耗量大的代碼,會嚴重影響系統的性能!
1) 若是返回nil,表示沒有響應的視圖
2) 若是返回視圖,表示該視圖接收用戶的響應
接收用戶觸摸響應的幾個條件
1) self.userInteractionEnabled = YES; 容許接收用戶響應
2) self.hidden = NO; 只有現實的視圖才能接收用戶觸摸
3) self.alpha > 0.01; 視圖的透明度必定要可見
提示:並非全部的控件都默認接收用戶交互的,譬如:UIImageView,UILabel等
參數說明
point 用戶觸摸的點,相對於當前視圖座標系的座標點
event 用戶觸摸事件,開發中通常程序員不使用,該事件用於在響應者鏈條上傳遞