Button 點(diǎn)擊響應(yīng)

在一個(gè)app中間有一個(gè)button趣苏,在你手觸摸屏幕點(diǎn)擊后枪汪,到這個(gè)button收到點(diǎn)擊事件,中間發(fā)生了什么呢?

上面這個(gè)問(wèn)題回官,已經(jīng)成了一道經(jīng)典的面試題啦第献,今天我在某個(gè)頁(yè)面布局的時(shí)候衬吆,發(fā)現(xiàn)button的點(diǎn)擊事件一直無(wú)效秸滴,把我知道會(huì)犯的錯(cuò)都嘗試了一遍,然而還是沒(méi)用栈源,困擾我老久了挡爵,趁此機(jī)會(huì)再次把UIButton的響應(yīng)鏈再了解一遍。

孤零零的 Button

在此我們需要先了解一下甚垦,UIResponder茶鹃,也許我們很少會(huì)直接用到它,但是基本上我們所能看到的所有圖形界面都是繼承自它的哦艰亮,它掌管著操作事件分發(fā)大權(quán)闭翩。

UIResponder

拿上述 Button 舉例, 此處用一下 nextResponder

- (IBAction)buttonAction:(id)sender {
    
    UIButton *button = (UIButton *)sender;
    NSLog(@"%@",button);
    NSLog(@"%@",button.nextResponder);
    NSLog(@"%@",button.nextResponder.nextResponder);
    NSLog(@"%@",button.nextResponder.nextResponder.nextResponder);
    NSLog(@"%@",button.nextResponder.nextResponder.nextResponder.nextResponder);
    NSLog(@"%@",button.nextResponder.nextResponder.nextResponder.nextResponder.nextResponder);
}
2016-07-08 22:25:56.268 TestButton[55893:12560428] <UIButton: 0x7faad3f1b850; frame = (184 353; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7faad3f1bdc0>>
2016-07-08 22:25:56.269 TestButton[55893:12560428] <UIView: 0x7faad3d27ca0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x7faad3d0a0d0>>
2016-07-08 22:25:56.269 TestButton[55893:12560428] <ViewController: 0x7faad3c65ed0>
2016-07-08 22:25:56.269 TestButton[55893:12560428] <UIWindow: 0x7faad3e51ab0; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x7faad3c67380>; layer = <UIWindowLayer: 0x7faad3c63e30>>
2016-07-08 22:25:56.269 TestButton[55893:12560428] <UIApplication: 0x7faad3c049e0>
2016-07-08 22:25:56.269 TestButton[55893:12560428] <AppDelegate: 0x7faad3d19050>

同時(shí)也可以看出這個(gè)最基本button 的響應(yīng)鏈。注意此處是通過(guò)[self.nextResponder touchesBegan:touches withEvent:event] 傳遞給下一個(gè) nextResponder 的迄埃,一般我們手動(dòng)重寫(xiě)了 touch 事件時(shí)就有可能中斷它的過(guò)程疗韵,當(dāng)然很多時(shí)候是用來(lái)監(jiān)聽(tīng)觀察的。

響應(yīng)鏈

然后UIApplication接收到手指的事件之后侄非,就會(huì)去調(diào)用UIWindow的hitTest:withEvent:蕉汪,看看當(dāng)前點(diǎn)擊的點(diǎn)是不是在window內(nèi)流译,如果是則繼續(xù)依次調(diào)用subView的hitTest:withEvent:方法,直到找到最后需要的view者疤。

/** point :是否在view的frame范圍內(nèi)福澡, event: 傳過(guò)來(lái)的UITouchEvent*/
// 該方法用來(lái)判斷點(diǎn)擊事件發(fā)生的位置是否處于當(dāng)前視圖范圍內(nèi),以確定用戶是不是點(diǎn)擊了當(dāng)前視圖
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
// 若上述方法返回YES,則向當(dāng)前視圖的所有子視圖(subviews)發(fā)送下面該事件驹马,直到有子視圖返回非空對(duì)象或者全部子視圖遍歷完畢
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
/**
    如所有子視圖都返回非革砸,則hitTest:withEvent:方法返回自身(self)。
    也就是找到了最后需要的 View.
*/

官方一點(diǎn)的解釋hit-test view : 手指觸摸(Touch)操作時(shí)會(huì)將其打包成一個(gè)UIEvent對(duì)象糯累,并放入當(dāng)前活動(dòng)Application的事件隊(duì)列算利,單例的UIApplication會(huì)從事件隊(duì)列中取出觸摸事件并傳遞給單例的UIWindow來(lái)處理,UIWindow對(duì)象首先會(huì)使用hitTest:withEvent:方法尋找此次Touch操作初始點(diǎn)所在的視圖(View)寇蚊,即需要將觸摸事件傳遞給其處理的視圖笔时,這個(gè)過(guò)程稱之為hit-test view。

注意: hitTest里面是有判斷當(dāng)前的view是否支持點(diǎn)擊事件仗岸,比如userInteractionEnabledhidden借笙、alpha等屬性扒怖,都會(huì)影響一個(gè)view是否可以相應(yīng)事件,如果不響應(yīng)則直接返回nil业稼。 所以常常我們一個(gè)點(diǎn)擊事件不能被除非通常也可能是上述幾種原因之一盗痒。

同時(shí)更詳細(xì)的iOS事件響應(yīng)鏈中Hit-Test View的應(yīng)用, 推薦看看,作者舉例說(shuō)明了幾個(gè)常用的擴(kuò)展低散,Hit-test view的應(yīng)用舉例還是不錯(cuò)的俯邓。

接下去,此時(shí)熔号,我們已經(jīng)找到了最終的 view啦稽鞭,看它具體需要做什么啦

 [button addTarget:self action:@selector(buttonTapDoSome) forControlEvents:UIControlEventTouchUpInside];

這個(gè)控件對(duì)象去觸發(fā)target對(duì)象上的action行為,來(lái)最終處理事件引镊。所以此處有順便了解下Target-Action朦蕴,Target-Action機(jī)制由兩部分組成:即目標(biāo)對(duì)象和行為Selector。目標(biāo)對(duì)象指定最終處理事件的對(duì)象弟头,而行為Selector則是處理事件的方法吩抓。

target_action 來(lái)自官方文檔

最后事件處理完成后,整個(gè)過(guò)程也就基本完成啦赴恨。

整個(gè)流程
  • 注意不能響應(yīng)的情況
1疹娶、userInteractionEnabled 交互是否打開(kāi)(本身和父視圖都要注意)
2、frame 子視圖的frame是否有超過(guò) 父視圖
3伦连、hidden 和 alpha也有可能

ps:我之前犯的錯(cuò)與這個(gè)不太對(duì)雨饺,是兩個(gè)對(duì)象之間無(wú)法響應(yīng)對(duì)方事件挣饥,從而導(dǎo)致無(wú)法傳遞事件。

備注參考:
https://www.zybuluo.com/MicroCai/note/66142
http://southpeak.github.io/blog/2015/12/13/cocoa-uikit-uicontrol/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沛膳,一起剝皮案震驚了整個(gè)濱河市扔枫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锹安,老刑警劉巖短荐,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異叹哭,居然都是意外死亡忍宋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)风罩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)糠排,“玉大人,你說(shuō)我怎么就攤上這事超升∪牖拢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵室琢,是天一觀的道長(zhǎng)乾闰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)盈滴,這世上最難降的妖魔是什么涯肩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮巢钓,結(jié)果婚禮上病苗,老公的妹妹穿的比我還像新娘。我一直安慰自己症汹,他們只是感情好硫朦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著烈菌,像睡著了一般阵幸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芽世,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天挚赊,我揣著相機(jī)與錄音,去河邊找鬼济瓢。 笑死荠割,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔑鹦,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼夺克,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了嚎朽?” 一聲冷哼從身側(cè)響起铺纽,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哟忍,沒(méi)想到半個(gè)月后狡门,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锅很,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年其馏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆安。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叛复,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扔仓,到底是詐尸還是另有隱情褐奥,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布当辐,位于F島的核電站抖僵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缘揪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一义桂、第九天 我趴在偏房一處隱蔽的房頂上張望找筝。 院中可真熱鬧,春花似錦慷吊、人聲如沸袖裕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)急鳄。三九已至,卻和暖如春堰酿,著一層夾襖步出監(jiān)牢的瞬間疾宏,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工触创, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坎藐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像岩馍,于是被迫代替她去往敵國(guó)和親碉咆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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