(七)UIControl

本文系轉(zhuǎn)載咒林,原文地址為iOS觸摸事件全家桶

UIControl是系統(tǒng)提供的能夠以target-action模式處理觸摸事件的控件垫竞,iOS中UIButton蛀序、UISegmentedControl、UISwitch等控件都是UIControl的子類引有。當UIControl跟蹤到觸摸事件時倦逐,會向其上添加的target發(fā)送事件以執(zhí)行action宫补。值得注意的是粉怕,UIConotrol是UIView的子類,因此本身也具備UIResponder應有的身份秉犹。

關(guān)于UIControl,此處介紹兩點:

  1. target-action執(zhí)行時機及過程
  2. 觸摸事件優(yōu)先級

target-action

  • target:處理交互事件的對象
  • action:處理交互事件的方式

UIControl作為能夠響應事件的控件崇堵,必然也需要待事件交互符合條件時才去響應鸳劳,因此也會跟蹤事件發(fā)生的過程。不同于UIResponder以及UIGestureRecognizer通過 touches 系列方法跟蹤涵紊,UIControl有其獨特的跟蹤方式:

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event;
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event;
- (void)endTrackingWithTouch:(nullable UITouch *)touch withEvent:(nullable UIEvent *)event;
- (void)cancelTrackingWithEvent:(nullable UIEvent *)event;

乍一看幔摸,這4個方法和UIResponder的那4個方法幾乎吻合抚太,只不過UIControl只能接收單點觸控,因此接收的參數(shù)是單個UITouch對象尿贫。這幾個方法的職能也和UIResponder一致庆亡,用來跟蹤觸摸的開始、滑動拼缝、結(jié)束彰亥、取消。不過继阻,UIControl本身也是UIResponder废酷,因此同樣有 touches 系列的4個方法。事實上墨辛,UIControl的 Tracking 系列方法是在 touch 系列方法內(nèi)部調(diào)用的趴俘。比如 beginTrackingWithTouch 是在 touchesBegan 方法內(nèi)部調(diào)用的, 因此它雖然也是UIResponder太惠,但 touches 系列方法的默認實現(xiàn)和UIResponder本類還是有區(qū)別的垛叨。

當UIControl跟蹤事件的過程中,識別出事件交互符合響應條件敛纲,就會觸發(fā)target-action進行響應剂癌。UIControl控件通過 addTarget:action:forControlEvents: 添加事件處理的target和action,當事件發(fā)生時旁壮,UIControl通知target執(zhí)行對應的action谐檀。說是“通知”其實很籠統(tǒng)桐猬,事實上這里有個action傳遞的過程。當UIControl監(jiān)聽到需要處理的交互事件時溃肪,會調(diào)用 sendAction:to:forEvent: 將target惫撰、action以及event對象發(fā)送給全局應用,Application對象再通過 sendAction:to:from:forEvent: 向target發(fā)送action扼雏。

image

因此呢蛤,可以通過重寫UIControl的 sendAction:to:forEvent:sendAction:to:from:forEvent: 自定義事件執(zhí)行的target及action棍郎。

另外银室,若不指定target励翼,即 addTarget:action:forControlEvents: 時target傳空汽抚,那么當事件發(fā)生時伯病,Application會在響應鏈上從上往下尋找能響應action的對象。官方說明如下:

If you specify nil for the target object, the control searches the responder chain for an object that defines the specified action method.

觸摸事件優(yōu)先級

當原本關(guān)系已經(jīng)錯綜復雜的UIGestureRecognizer和UIResponder之間又冒出一個UIControl惭蟋,又會摩擦出什么樣的火花呢药磺?

In iOS 6.0 and later, default control actions prevent overlapping gesture recognizer behavior. For example, the default action for a button is a single tap. If you have a single tap gesture recognizer attached to a button’s parent view, and the user taps the button, then the button’s action method receives the touch event instead of the gesture recognizer.This applies only to gesture recognition that overlaps the default action for a control, which includes:

  • A single finger single tap on a UIButton, UISwitch, UIStepper, UISegmentedControl, and UIPageControl.
  • A single finger swipe on the knob of a UISlider, in a direction parallel to the slider.
  • A single finger pan gesture on the knob of a UISwitch, in a direction parallel to the switch.

簡單理解:UIControl會阻止父視圖上的手勢識別器行為癌佩,也就是UIControl處理事件的優(yōu)先級比UIGestureRecognizer高围辙,但前提是相比于父視圖上的手勢識別器。

image
  • 預置場景:在BlueView上添加一個button姚建,同時給button添加一個target-action事件怎囚。

    • 示例一:在BlueView上添加點擊手勢識別器
    • 示例二:在button上添加手勢識別器
  • 操作方式:單擊button

  • 測試結(jié)果:示例一中,button的target-action響應了單擊事件桥胞;示例二中恳守,BlueView上的手勢識別器響應了事件。過程日志打印如下:

    //示例一
    -[CLTapGestureRecognizer touchesBegan:withEvent:]
    -[CLButton touchesBegan:withEvent:]
    -[CLButton beginTrackingWithTouch:withEvent:]
    -[CLTapGestureRecognizer touchesEnded:withEvent:] after called state = 5
    -[CLButton touchesEnded:withEvent:]
    -[CLButton endTrackingWithTouch:withEvent:]
    按鈕點擊
    
    
    //示例二
    -[CLTapGestureRecognizer touchesBegan:withEvent:]
    -[CLButton touchesBegan:withEvent:]
    -[CLButton beginTrackingWithTouch:withEvent:]
    -[CLTapGestureRecognizer touchesEnded:withEvent:] after called state = 3
    手勢觸發(fā)
    -[CLButton touchesCancelled:withEvent:]
    -[CLButton cancelTrackingWithEvent:]
    
    
  • 原因分析:點擊button后贩虾,事件先傳遞給手勢識別器催烘,再傳遞給作為hit-tested view存在的button(UIControl本身也是UIResponder,這一過程和普通事件響應者無異)缎罢。示例一中伊群,由于button阻止了父視圖BlueView中的手勢識別器的識別,導致手勢識別器識別失斀⑹肌(狀態(tài)為failed 枚舉值為5),button完全接手了事件的響應權(quán)咽袜,事件最終由button響應丸卷;示例二中,button未阻止其本身綁定的手勢識別器的識別询刹,因此手勢識別器先識別手勢并識別成功(狀態(tài)為ended 枚舉值為3)谜嫉,而后通知Application取消響應鏈對事件的響應萎坷,因為 touchesCancelled 被調(diào)用,同時 cancelTrackingWithEvent 跟著調(diào)用沐兰,因此button的target-action得不到執(zhí)行哆档。

  • 其他:經(jīng)測試,若示例一中的手勢識別器設置 cancelsTouchesInView 為NO住闯,手勢識別器和button都能響應事件瓜浸。也就是說這種情況下,button不會阻止父視圖中手勢識別器的識別比原。

  • 結(jié)論:UIControl比其父視圖上的手勢識別器具有更高的事件響應優(yōu)先級斟叼。

TODO:
上述過程中,手勢識別器在執(zhí)行touchesEnded時是根據(jù)什么將狀態(tài)置為ended還是failed的春寿?即根據(jù)什么判斷應當識別成功還是識別失斃噬?

糾正 2017.11.17

以上所述UIControl的響應優(yōu)先級比手勢識別器高的說法不準確绑改,準確地說只適用于系統(tǒng)提供的有默認action操作的UIControl谢床,例如UIbutton、UISwitch等的單擊厘线,而對于自定義的UIControl识腿,經(jīng)驗證,響應優(yōu)先級比手勢識別器低造壮。讀者可自行驗證渡讼,感謝 @閆仕偉 同學的糾正。

下一篇 (八)解釋栗子

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耳璧,一起剝皮案震驚了整個濱河市成箫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旨枯,老刑警劉巖蹬昌,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異攀隔,居然都是意外死亡皂贩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門昆汹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來明刷,“玉大人,你說我怎么就攤上這事满粗”材” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長本冲。 經(jīng)常有香客問我,道長劫扒,這世上最難降的妖魔是什么檬洞? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮沟饥,結(jié)果婚禮上添怔,老公的妹妹穿的比我還像新娘。我一直安慰自己贤旷,他們只是感情好广料,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幼驶,像睡著了一般艾杏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盅藻,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天购桑,我揣著相機與錄音,去河邊找鬼氏淑。 笑死勃蜘,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的假残。 我是一名探鬼主播缭贡,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辉懒!你這毒婦竟也來了阳惹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤眶俩,失蹤者是張志新(化名)和其女友劉穎穆端,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仿便,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡体啰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗽仪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荒勇。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖闻坚,靈堂內(nèi)的尸體忽然破棺而出沽翔,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布仅偎,位于F島的核電站跨蟹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橘沥。R本人自食惡果不足惜窗轩,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望座咆。 院中可真熱鬧痢艺,春花似錦、人聲如沸介陶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哺呜。三九已至舌缤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間某残,已是汗流浹背友驮。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留驾锰,地道東北人卸留。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像椭豫,于是被迫代替她去往敵國和親耻瑟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 本文主要講解iOS觸摸事件的一系列機制赏酥,涉及的問題大致包括: 觸摸事件由觸屏生成后如何傳遞到當前應用喳整? 應用接收觸...
    baihualinxin閱讀 1,203評論 0 9
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件。本想自己總結(jié)一下裸扶,但是遇到了這篇文章框都,感覺總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載呵晨。作者:L...
    WQ_UESTC閱讀 5,996評論 4 26
  • 轉(zhuǎn)載: https://blog.csdn.net/qq871531334/article/details/822...
    NicooYang閱讀 1,583評論 0 9
  • 在開發(fā)過程中摸屠,大家或多或少的都會碰到令人頭疼的手勢沖突問題谓罗,正好前兩天碰到一個類似的bug,于是借著這個機會了解了...
    閆仕偉閱讀 5,305評論 2 23
  • 觸摸事件的生命周期 當我們手指觸碰屏幕的那一刻季二,一個觸摸事件便產(chǎn)生了檩咱。經(jīng)過進程間通信揭措,觸摸事件被傳遞到合適的應用之...
    Gintok閱讀 1,344評論 0 3