知 識(shí) 點(diǎn) / 超 人
觸摸事件分為四個(gè)階段進(jìn)行傳遞:
1.硬件響應(yīng)階段
2.系統(tǒng)響應(yīng)階段
3.桌面響應(yīng)階段
4.應(yīng)用響應(yīng)階段
- 4.1事件傳遞
- 4.2尋找最佳響應(yīng)者
- 4.3事件傳遞的響應(yīng)鏈
硬件響應(yīng)階段
該階段是用戶觸摸到電容屏,電容屏響應(yīng)并產(chǎn)生觸摸信號(hào)的階段
知識(shí)點(diǎn)補(bǔ)充:
電容屏原理(百度百科)
電容技術(shù)觸摸面板CTP是利用人體的電流感應(yīng)進(jìn)行工作的银酗。電容屏是一塊四層復(fù)合玻璃屏,玻璃屏的內(nèi)表面和夾層各涂一層ITO(納米銦錫金屬氧化物)爆侣,最外層是只有0.0015mm厚的矽土玻璃保護(hù)層,夾層ITO涂層作工作面歌馍,四個(gè)角引出四個(gè)電極报慕,內(nèi)層ITO為屏層以保證工作環(huán)境豆巨。
當(dāng)用戶觸摸電容屏?xí)r,由于人體電場(chǎng)元扔,用戶手指和工作面形成一個(gè)耦合電容躯保,因?yàn)楣ぷ髅嫔辖佑懈哳l信號(hào),于是手指吸收走一個(gè)很小的電流澎语,這個(gè)電流分別從屏的四個(gè)角上的電極中流出途事,且理論上流經(jīng)四個(gè)電極的電流與手指頭到四角的距離成比例,控制器通過(guò)對(duì)四個(gè)電流比例的精密計(jì)算擅羞,得出位置尸变。可以達(dá)到99%的精確度减俏,具備小于3ms的響應(yīng)速度召烂。電容屏觸摸點(diǎn)計(jì)算:
電容屏是在兩層ITO導(dǎo)電玻璃涂層上蝕刻出不同的ITO導(dǎo)電線路模塊。兩個(gè)模塊上蝕刻的圖形相互垂直垄懂,可以把它們看作是X和Y方向 連續(xù)變化的滑條骑晶。由于X痛垛、Y架構(gòu)在不同表面,其相交處形成一電容節(jié)點(diǎn)桶蛔。一個(gè)滑條可以當(dāng)成驅(qū)動(dòng)線匙头,另外一個(gè)滑條當(dāng)成是偵測(cè)線。當(dāng)電流經(jīng)過(guò)驅(qū)動(dòng)線中的一條導(dǎo)線時(shí)仔雷,如果外界有電容變化的信號(hào)蹂析,那么就會(huì)引起另一層導(dǎo)線上電容節(jié)點(diǎn)的變化。偵測(cè)電容值的變化可以通過(guò)與之相連的電子回路測(cè)量得到碟婆,再經(jīng)由A/D控制器轉(zhuǎn)為數(shù)字訊號(hào)讓計(jì)算機(jī)做運(yùn)算處理取得(X电抚,Y) 軸位置,進(jìn)而達(dá)到定位的目地竖共。
多點(diǎn)操作時(shí)蝙叛,控制器先后供電流給驅(qū)動(dòng)線,因而使各節(jié)點(diǎn)與導(dǎo)線間形成一特定電場(chǎng)公给。然后逐列掃描感測(cè)線測(cè)量其電極間的電容變化量借帘,從而達(dá)成多點(diǎn)定位。
響應(yīng)時(shí)間:響應(yīng)時(shí)間定義為淌铐,觸摸屏上手指觸碰事件與觸摸屏控制器產(chǎn)生中斷信號(hào)之間的時(shí)間肺然。
響應(yīng)步驟:
*第一步: ->用戶觸摸電容屏
*第二步: ->電容屏根據(jù)電流產(chǎn)生反應(yīng)
*第三步: ->電容屏控制芯片計(jì)算出觸控點(diǎn)產(chǎn)生電容信號(hào)
*第四步: ->CPU處理信號(hào)
系統(tǒng)響應(yīng)階段
該階段是iOS系統(tǒng)對(duì)CPU指令封裝的階段
知識(shí)點(diǎn)補(bǔ)充:
IOKit.framework
是與硬件或內(nèi)核服務(wù)通信的底層框架,主要是面向硬件驅(qū)動(dòng)開發(fā)者腿准。在 IOKit 里面际起,所有的通信都通過(guò) IOKit Master Port 來(lái)進(jìn)行。雖然這是一個(gè)公共框架吐葱,但蘋果不鼓勵(lì)開發(fā)者使用它街望,任何使用它的應(yīng)用程序都將被AppStore拒絕。這里有蘋果官方對(duì)IOKit.framework的說(shuō)明IPC 通信:跨進(jìn)程通信唇撬。
Mach Port
是在系統(tǒng)內(nèi)核實(shí)現(xiàn)和維護(hù)的一種 IPC 消息隊(duì)列它匕,它持有用于 IPC 通信的 mach messages,可以看做是一個(gè)單向的數(shù)據(jù)發(fā)送渠道
窖认,構(gòu)建一個(gè)消息結(jié)構(gòu)體后通過(guò)mach_msg() 方法發(fā)送消息出去。只有一個(gè)進(jìn)程可以從對(duì)應(yīng)的 port 里 dequeue 一條消息告希,這個(gè)進(jìn)程被稱為接收端(receive-right)
扑浸。可以有多個(gè)進(jìn)程往某個(gè) port 里 enqueue 消息燕偶,這些進(jìn)程稱為發(fā)送端(send-rights)
喝噪。因?yàn)橹荒軉蜗虬l(fā)送,所以當(dāng) B 進(jìn)程收到了 A 進(jìn)程發(fā)來(lái)的消息之后要自己創(chuàng)建一個(gè)新的 Port 然后又發(fā)回去 A 進(jìn)程指么。B要發(fā)消息給A酝惧,必須先知道 A進(jìn)程的 port 信息我們才能往里面發(fā)消息榴鼎。XNU 系統(tǒng)提供了bootstrap port
這個(gè)東西,由系統(tǒng)提供查詢服務(wù)晚唇,這樣所有的進(jìn)程都可以去廣播自己的 mach port 接收端的名字巫财,也可以查詢其他進(jìn)程的名字。
響應(yīng)步驟:
*第一步: ->CPU處理信號(hào)轉(zhuǎn)為指令
*第二步: ->iOS系統(tǒng)的輸入輸出驅(qū)動(dòng)IOKit.framework接收
*第三步: ->IOKit封裝觸摸事件為IOHIDEvent對(duì)象
*第四步: ->IOKit通過(guò)mach prot(IPC)將IOHIDEvent事件轉(zhuǎn)發(fā)給SpringBoard.app
桌面響應(yīng)階段
該階段是iOS桌面進(jìn)程響應(yīng)處理階段
知識(shí)點(diǎn)補(bǔ)充:
APP運(yùn)行的過(guò)程本質(zhì)上是處理各種事件的過(guò)程哩陕,把事件進(jìn)行分類平项,系統(tǒng)層事件、應(yīng)用層事件悍及、特殊事件闽瓢。source1基本就是系統(tǒng)事件,source0基本就是應(yīng)用層事件心赶。
SpringBoard.app
用來(lái)管理iOS的主屏幕的應(yīng)用程序扣讼,啟動(dòng)WindowSever(窗口服務(wù)器),bootstrapping(引導(dǎo)應(yīng)用程序),以及在啟動(dòng)時(shí)候系統(tǒng)的一些初始化設(shè)置都是由這個(gè)特定的應(yīng)用程序負(fù)責(zé)的。當(dāng)觸摸事件發(fā)生時(shí)缨叫,只有負(fù)責(zé)管理屏幕的SpringBoard.app才知道如何正確的響應(yīng)處理事件届谈。因?yàn)橹挥蠸pringBoard.app才知道屏幕處于什么狀態(tài),是有應(yīng)用在前臺(tái)活躍著弯汰,還是沒(méi)有應(yīng)用在前臺(tái)艰山,如果沒(méi)有應(yīng)用在前臺(tái)則說(shuō)明在桌面,則由SpringBoard.app進(jìn)入內(nèi)部響應(yīng)咏闪,觸發(fā)Source0回調(diào)曙搬。如果有應(yīng)用在前臺(tái)則通過(guò)mach port(IPC)轉(zhuǎn)發(fā)給對(duì)應(yīng)App。Source1
基于 mach port的處理事件 鸽嫂,蘋果注冊(cè)了一個(gè) Source1 用來(lái)接收系統(tǒng)事件纵装,其回調(diào)函數(shù)為 __IOHIDEventSystemClientQueueCallback()。觸發(fā)回調(diào)后据某,會(huì)調(diào)用 _UIApplicationHandleEventQueue() 進(jìn)行應(yīng)用內(nèi)部的事件分發(fā)鹊杖。Source0
非基于Port的 處理事件,什么叫非基于Port的呢匿又?就是說(shuō)這個(gè)消息不是其他進(jìn)程或者內(nèi)核直接發(fā)送的程拭。一般是APP內(nèi)部的事件, 比如hitTest:withEvent的處理, performSelectors的事件。
該階段分為兩種情況筷狼,無(wú)前臺(tái)App的響應(yīng)步驟瓶籽、有前臺(tái)App的響應(yīng)步驟。本質(zhì)上來(lái)說(shuō)是一樣的埂材。因?yàn)镾pringBoard.app本身也是App
無(wú)前臺(tái)App的響應(yīng)步驟:
*第一步:->SpringBoard.app的主線程的MainRunloop收到IOKit.framework轉(zhuǎn)發(fā)來(lái)的消息后蘇醒
*第二步:->SpringBoard.app通過(guò)注冊(cè)的source1的回調(diào)函數(shù)__IOHIDEventSystemClientQueueCallback()接收IOHIDEvent事件
*第三步:->SpringBoard.app判斷是否由誰(shuí)響應(yīng)IOHIDEvent事件
*第四步:->發(fā)現(xiàn)無(wú)前臺(tái)App
*第五步:->觸發(fā)SpringBoard.app內(nèi)部的source0回調(diào)函數(shù)__UIApplicationHandleEventQueue()
*第六步:->由SpringBoard.app內(nèi)部自行處理
有前臺(tái)App的響應(yīng)步驟:
*第一步:->SpringBoard.app的主線程的MainRunloop收到IOKit.framework轉(zhuǎn)發(fā)來(lái)的消息后蘇醒
*第二步:->SpringBoard.app通過(guò)注冊(cè)的source1的回調(diào)函數(shù)__IOHIDEventSystemClientQueueCallback()接收IOHIDEvent事件
*第三步:->SpringBoard.app判斷是否由誰(shuí)響應(yīng)IOHIDEvent事件
*第四步:->發(fā)現(xiàn)有前臺(tái)App
*第五步:->通過(guò)mach port將IOHIDEvent事件轉(zhuǎn)發(fā)給對(duì)應(yīng)前臺(tái)App
應(yīng)用響應(yīng)階段
該階段是App內(nèi)部的響應(yīng)處理階段塑顺,比較復(fù)雜。內(nèi)容比較多俏险,因此知識(shí)點(diǎn)補(bǔ)充放在了最后严拒,請(qǐng)耐心看扬绪。
我把該階段細(xì)分為三個(gè)小階段:
第一階段:->事件傳遞
第二階段:->尋找最佳響應(yīng)者
第三階段:->事件傳遞的響應(yīng)鏈
第一階段: 事件傳遞響應(yīng)步驟:
*第一步: ->App主線程的MainRunloop收到消息后蘇醒
*第二步: ->通過(guò)App的source1的回調(diào)函數(shù)__IOHIDEventSystemClientQueueCallback()接收IOHIDEvent事件
*第三步: ->source1內(nèi)部觸發(fā)source0的回調(diào)函數(shù)__UIApplicationHandleEventQueue()
*第四步: ->source0內(nèi)部對(duì)IOHIDEvent進(jìn)行封裝處理成UIEvent
*第五步: ->soucre0內(nèi)部調(diào)用UIApplication的sendEvent:方法,將UIEvent傳給UIWindow(不一定是KeyWindow裤唠,如果有多個(gè)window挤牛,則會(huì)傳遞給最上層的window)
第二階段: 尋找最佳響應(yīng)者:
*第一步: ->UIWindow通過(guò)hitTest:withEvent:與pointInside:withEvent:方法從UIView層級(jí)的最頂層往最底層遞歸查詢由那一層View是最佳的事件響應(yīng)者。
*第二步: -> 首先通過(guò)hitTest:withEvent:方法判斷該視圖是否能響應(yīng)事件巧骚,userInteractionEnabled赊颠、hidden、alpha三個(gè)屬性判斷該界面是否能響應(yīng)事件
*第三步: -> 然后通過(guò)pointInside:withEvent:方法判斷觸摸點(diǎn)是否在該View中
*第四步: -> 最后判斷該View是否有子視圖劈彪,如果有子視圖則遞歸判斷子視圖是否能響應(yīng)竣蹦,如果能響應(yīng)則在hitTest:withEvent:方法中返回子視圖作為最佳響應(yīng)者,如果子視圖不能響應(yīng)沧奴,則返回本身View作為最佳響應(yīng)者
第三階段: 事件傳遞的響應(yīng)鏈:
該階段有兩種情況痘括,有手勢(shì)識(shí)別器、沒(méi)有手勢(shì)識(shí)別器滔吠。
有手勢(shì)識(shí)別器的傳遞:
*第一步: ->判斷是否有手勢(shì)識(shí)別器
*第二步: ->有手勢(shì)識(shí)別器
*第三步: ->首先把事件傳遞給手勢(shì)識(shí)別器纲菌,手勢(shì)識(shí)別器接收事件,調(diào)用touchesBegan方法,并進(jìn)入手勢(shì)識(shí)別器UIGestureRecognizer的響應(yīng)鏈傳遞
*第四步: ->然后把事件傳遞給最佳響應(yīng)者疮绷,調(diào)用最佳響應(yīng)者自身的touchesBegan方法翰舌,并進(jìn)入U(xiǎn)IResponder的響應(yīng)鏈傳遞。
*第五步: ->手勢(shì)識(shí)別器自底向上的進(jìn)行事件傳遞冬骚,直到上面某一層不響應(yīng)則斷層椅贱,會(huì)分別調(diào)用每層響應(yīng)者手勢(shì)識(shí)別器的touchesMoved、touchesEnded方法只冻。
*第六步: ->手勢(shì)識(shí)別器最終成功識(shí)別手勢(shì)并執(zhí)行任務(wù)
*第七步: ->手勢(shì)識(shí)別器調(diào)用響應(yīng)者的touchesCancelled方法來(lái)終止最佳響應(yīng)者對(duì)于事件的響應(yīng)庇麦。(因此最佳響應(yīng)者自身并不會(huì)調(diào)touchesMoved、touchesEnded方法)
沒(méi)有手勢(shì)識(shí)別器的傳遞:
*第一步: ->判斷是否有手勢(shì)識(shí)別器
*第二步: ->沒(méi)有手勢(shì)識(shí)別器
*第三步: ->把事件傳遞給最佳響應(yīng)者喜德,調(diào)用最佳響應(yīng)者自身的touchesBegan方法山橄,并進(jìn)入U(xiǎn)IResponder的響應(yīng)鏈傳遞。
*第四步: ->最佳響應(yīng)者自底向上的進(jìn)行事件傳遞舍悯,直到上面某一層不響應(yīng)則斷層航棱,會(huì)分別調(diào)用每層響應(yīng)者的touchesMoved、touchesEnded方法贱呐。
*第五步: ->最佳響應(yīng)者最終成功識(shí)別事件并執(zhí)行任務(wù)
知識(shí)點(diǎn)補(bǔ)充:
響應(yīng)鏈
上圖是官網(wǎng)對(duì)于響應(yīng)鏈的示例展示丧诺,如果最佳響應(yīng)者對(duì)象是UITextField,則響應(yīng)鏈為:
UITextField->UIView->UIView->UIViewController->UIWindow->UIApplication->UIApplicationDelegate
如果一直沒(méi)有UIResponder做響應(yīng)處理奄薇,則這些UITouches到達(dá)最后的響應(yīng)者即UIApplication后,就被忽略而消失抗愁。
UIGestureRecognizer馁蒂、UIResponder呵晚、UIControl
這里只做簡(jiǎn)單的介紹,不做深入探討
UIGestureRecognizer
手勢(shì)識(shí)別器沫屡,繼承NSObject饵隙,UIGestureRecognizer是一個(gè)抽象類
,因此我們只能使用它的子類:
UITapGestureRecognizer
(點(diǎn)擊)
UIPinchGestureRecognizer
(捏合)
UIRotationGestureRecognizer
(旋轉(zhuǎn))
UISwipeGestureRecognizer
(滑動(dòng)沮脖,快速移動(dòng)金矛,是用于監(jiān)測(cè)滑動(dòng)的方向的)
UIPanGestureRecognizer
(拖移,慢速移動(dòng)勺届,是用于監(jiān)測(cè)偏移的量的)
UILongPressGestureRecognizer
(長(zhǎng)按)手勢(shì)識(shí)別是具有
互斥原則
的驶俊,例如 Tap 一次與Tap 兩次、Tap 與 LongPress免姿、Swipe與 Pan饼酿。比如單擊和雙擊,如果它識(shí)別出一種手勢(shì)胚膊,其后的手勢(shì)將不被識(shí)別故俐。所以對(duì)于關(guān)聯(lián)手勢(shì),要做特殊處理來(lái)幫助程序進(jìn)行甄別(requireGestureRecognizerToFail:方法)紊婉。應(yīng)該先把當(dāng)前手勢(shì)歸于一類手勢(shì)里面药版,然后做一個(gè)特殊處理邏輯,判斷手勢(shì)是否是雙擊喻犁,如果是雙擊則相應(yīng)雙擊事件槽片,如果雙擊失效,則作為單擊手勢(shì)處理株汉。
其核心就是設(shè)置delegate和在需要手勢(shì)監(jiān)測(cè)的view上使用addGestureRecognizer添加指定的手勢(shì)監(jiān)測(cè)筐乳。
當(dāng)然要記得在作為delegate的view的頭文件加上<UIGestureRecognizerDelegate>。
常用屬性介紹
//當(dāng)前手勢(shì)的狀態(tài)
@property(nonatomic,readonly) UIGestureRecognizerState state;
//設(shè)置代理
@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate;
//設(shè)置手勢(shì)是否有效
@property(nonatomic, getter=isEnabled) BOOL enabled;
//獲取手勢(shì)所在的view
@property(nullable, nonatomic,readonly) UIView *view;
//獲取觸發(fā)觸摸的點(diǎn)
-(CGPoint)locationInView:(nullable UIView*)view;
//設(shè)置觸摸點(diǎn)數(shù)
-(NSUInteger)numberOfTouches;
//獲取某一個(gè)觸摸點(diǎn)的觸摸位置
-(CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;
//調(diào)用對(duì)象是需要失效的手勢(shì)乔妈,參數(shù)對(duì)象是生效的手勢(shì)蝙云。如果生效手勢(shì)失效,則調(diào)用對(duì)象手勢(shì)生效
-(void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
//獲取到的是手指移動(dòng)后路召,在相對(duì)坐標(biāo)中的偏移量
-(CGPoint)translationInView:(nullable UIView *)view;
/**
當(dāng)這個(gè)屬性設(shè)置為YES時(shí)勃刨,默認(rèn)為YES
如果識(shí)別到了手勢(shì),系統(tǒng)將會(huì)發(fā)送touchesCancelled:withEvent:消息在其事件傳遞的響應(yīng)鏈上股淡,終止觸摸事件的傳遞身隐。
設(shè)置為NO時(shí)
則不會(huì)終止事件的傳遞
*/
@property(nonatomic) BOOL cancelsTouchesInView;
/**
當(dāng)這個(gè)屬性設(shè)置為NO時(shí),默認(rèn)為NO
手勢(shì)識(shí)別器識(shí)別手勢(shì)期間唯灵,觸摸對(duì)象就算狀態(tài)發(fā)生變化贾铝,也會(huì)發(fā)送事件給最佳響應(yīng)者
設(shè)置為YES時(shí)
識(shí)別手勢(shì)期間,觸摸狀態(tài)若發(fā)生變化,則不會(huì)發(fā)送事件給最佳響應(yīng)者垢揩。
*/
@property(nonatomic) BOOL delaysTouchesBegan;
/**
當(dāng)這個(gè)屬性設(shè)置為NO時(shí)玖绿,默認(rèn)為NO
在手勢(shì)識(shí)別成功后,發(fā)送touchesCancelled,手勢(shì)識(shí)別失敗時(shí)叁巨,發(fā)送touchesEnded
設(shè)置為YES時(shí)
在手勢(shì)識(shí)別成功后,發(fā)送touchesCancelled斑匪,手勢(shì)識(shí)別失敗時(shí),會(huì)延遲大概0.15ms,期間沒(méi)有接收到別的touch才會(huì)發(fā)送touchesEnded
*/
@property(nonatomic) BOOL delaysTouchesEnded
UIGestureRecognizerDelegate方法介紹
//手指觸摸屏幕后回調(diào)的方法锋勺,返回NO則不再進(jìn)行手勢(shì)識(shí)別蚀瘸,方法觸發(fā)等
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
//開始進(jìn)行手勢(shì)識(shí)別時(shí)調(diào)用的方法,返回NO則結(jié)束庶橱,不再觸發(fā)手勢(shì)
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
//是否支持多時(shí)候觸發(fā)贮勃,返回YES,則可以多個(gè)手勢(shì)一起觸發(fā)方法悬包,返回NO則為互斥
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
//下面這個(gè)兩個(gè)方法也是用來(lái)控制手勢(shì)的互斥執(zhí)行的
//這個(gè)方法返回YES衙猪,第一個(gè)手勢(shì)和第二個(gè)互斥時(shí),第一個(gè)會(huì)失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
//這個(gè)方法返回YES布近,第一個(gè)和第二個(gè)互斥時(shí)垫释,第二個(gè)會(huì)失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
手勢(shì)狀態(tài)介紹
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
UIGestureRecognizerStatePossible, // 已經(jīng)觸發(fā)了觸摸事件,但尚未識(shí)別是何種手勢(shì)操作撑瞧,默認(rèn)狀態(tài)
UIGestureRecognizerStateBegan, // 手勢(shì)已經(jīng)開始棵譬,此時(shí)已經(jīng)被識(shí)別,但是這個(gè)過(guò)程中可能發(fā)生變化预伺,手勢(shì)操作尚未完成
UIGestureRecognizerStateChanged, // 手勢(shì)狀態(tài)發(fā)生轉(zhuǎn)變
UIGestureRecognizerStateEnded, // 手勢(shì)識(shí)別操作完成(此時(shí)已經(jīng)松開手指)
UIGestureRecognizerStateCancelled, // 手勢(shì)被取消订咸,恢復(fù)到默認(rèn)狀態(tài)
UIGestureRecognizerStateFailed, // 手勢(shì)識(shí)別失敗,恢復(fù)到默認(rèn)狀態(tài)
UIGestureRecognizerStateRecognized // 手勢(shì)識(shí)別完成酬诀,同UIGestureRecognizerStateEnded
UIGestureRecognizerStateEnded // 手勢(shì)識(shí)別完成
};
UIResponder
是專門用來(lái)響應(yīng)用戶的操作處理和各種事件的類脏嚷,包括觸摸事件(Touch Events)、運(yùn)動(dòng)事件(Motion Events)瞒御、遠(yuǎn)程控制事件(Remote Control Events)父叙,UIResponder是一個(gè)抽象類
,因此我們主要是使用它的子類:
UIApplication
UIViewController
UIView
UIWindow
(它能響應(yīng)事件是因?yàn)樗母割愂荱IView肴裙,而UIView是UIResponder的子類)
常用方法介紹
//對(duì)象是否能成為第一響應(yīng)者 YES表示能成為
- (BOOL)canBecomeFirstResponder
//設(shè)置對(duì)象成為第一響應(yīng)者
- (void)becomeFirstResponder
//對(duì)象是否能失去第一響應(yīng)者的資格 YES表示能
- (BOOL)canResignFirstResponder
//取消對(duì)象的第一響應(yīng)者資格
- (void)resignFirstResponder
//手指觸碰屏幕趾唱,觸摸開始
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//手指在屏幕上移動(dòng)
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//手指離開屏幕,觸摸結(jié)束
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//觸摸結(jié)束前蜻懦,某個(gè)系統(tǒng)事件中斷了觸摸甜癞,例如電話呼入
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
UIControl
是UIView的子類,因此也是UIResponder的子類宛乃,UIControl是一個(gè)抽象類
悠咱,因此我們主要使用它的子類:
UIButton
UISwitch
UITextField
UIControl采用了一種不同于UIResponder的處理機(jī)制蒸辆,它將標(biāo)準(zhǔn)的觸摸事件轉(zhuǎn)換封裝成為易于使用的特殊的控件事件,例如通過(guò)UIControl對(duì)象處理后乔煞,按下按鈕的事件就被封裝成一個(gè)控件事件吁朦,而不用去判斷觸摸屏幕的整個(gè)操作過(guò)程柒室。
例如使用繼承之UIControl的UIButton時(shí)渡贾,為UIButton對(duì)象添加觸摸事件
例如:
UIButton *button = [UIButton new];
[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEvents];
button
:是要響應(yīng)事件的控件對(duì)象。
self
:是要把觸摸事件的消息發(fā)送到哪個(gè)對(duì)象里去雄右。
@selector(buttonAction)
:后面是一個(gè)方法選擇器空骚,表示該事件需要響應(yīng)的方法,方法里面是執(zhí)行的任務(wù)擂仍;
UIControlEvents
:是事件類型囤屹,表示響應(yīng)什么樣的事件。
UIControlEvents事件類型介紹
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
UIControlEventTouchDown = 1 << 0, // 單點(diǎn)觸摸按下事件:用戶點(diǎn)觸屏幕或者又有新的手指落下的時(shí)候逢渔。
UIControlEventTouchDownRepeat = 1 << 1, //多點(diǎn)觸摸按下事件肋坚,點(diǎn)觸計(jì)數(shù)大于1:用戶按下第二、三肃廓、或第四根手指的時(shí)候智厌。
UIControlEventTouchDragInside = 1 << 2, //當(dāng)一次觸摸在控件窗口內(nèi)拖動(dòng)時(shí)。
UIControlEventTouchDragOutside = 1 << 3, //當(dāng)一次觸摸在控件窗口之外拖動(dòng)時(shí)盲赊。
UIControlEventTouchDragEnter = 1 << 4, //當(dāng)一次觸摸從控件窗口之外拖動(dòng)到內(nèi)部時(shí)铣鹏。
UIControlEventTouchDragExit = 1 << 5, //當(dāng)一次觸摸從控件窗口內(nèi)部拖動(dòng)到外部時(shí)。
UIControlEventTouchUpInside = 1 << 6, //所有在控件之內(nèi)觸摸抬起事件哀蘑。
UIControlEventTouchUpOutside = 1 << 7, //所有在控件之外觸摸抬起事件(點(diǎn)觸必須開始與控件內(nèi)部才會(huì)發(fā)送通知)诚卸。
UIControlEventTouchCancel = 1 << 8, //所有觸摸取消事件,即一次觸摸因?yàn)榉派狭颂嗍种付蝗∠媲ǎ蛘弑簧湘i或者電話呼叫打斷合溺。
UIControlEventValueChanged = 1 << 12, // 當(dāng)控件的值發(fā)生改變時(shí),發(fā)送通知缀台。用于滑塊棠赛、分段控件、以及其他取值的控件将硝。你可以配置滑塊控件何時(shí)發(fā)送通知恭朗,在滑塊被放下時(shí)發(fā)送,或者在被拖動(dòng)時(shí)發(fā)送依疼。
UIControlEventPrimaryActionTriggered API_AVAILABLE(ios(9.0)) = 1 << 13, // 按鈕觸發(fā)的語(yǔ)義動(dòng)作
UIControlEventEditingDidBegin = 1 << 16, // 當(dāng)文本控件中開始編輯時(shí)發(fā)送通知痰腮。
UIControlEventEditingChanged = 1 << 17, //當(dāng)文本控件中的文本被改變時(shí)發(fā)送通知。
UIControlEventEditingDidEnd = 1 << 18, //當(dāng)文本控件中編輯結(jié)束時(shí)發(fā)送通知律罢。
UIControlEventEditingDidEndOnExit = 1 << 19, // 當(dāng)文本控件內(nèi)通過(guò)按下回車鍵(或等價(jià)行為)結(jié)束編輯時(shí)膀值,發(fā)送通知棍丐。
UIControlEventAllTouchEvents = 0x00000FFF, // 通知所有觸摸事件。
UIControlEventAllEditingEvents = 0x000F0000, // 通知所有關(guān)于文本編輯的事件沧踏。
UIControlEventApplicationReserved = 0x0F000000, // 應(yīng)用保留事件
UIControlEventSystemReserved = 0xF0000000, // 系統(tǒng)保留事件
UIControlEventAllEvents = 0xFFFFFFFF //通知所有事件
};
UIGestureRecognizer歌逢、UIResponder、翘狱、UIControl的優(yōu)先級(jí)
UIGestureRecognizer優(yōu)先級(jí) 大于 UIResponder優(yōu)先級(jí) 秘案,UIResponder優(yōu)先級(jí) 與 UIControl優(yōu)先級(jí) 相同
最后補(bǔ)充一張圖片