1. 程式人生 > >IOS —— UIButton被點選響應的背後

IOS —— UIButton被點選響應的背後

一天打漁,三天晒網。大家猴又是我,堅持在工作日中的一日一部落格。

今天聊的是有關上幾篇文章提到的<事件響應鏈>的後續。在點選Button時,響應事件的背後到底發生了什麼事

那提到文章內容前還是得複習一下的

事件傳遞,響應鏈到底是怎麼樣的呢?

至簡的回答,傳遞是自上往下。響應則相反,是自下往上的。

雖然說起來很簡單,但是在過程中涉及的方法還是比較多的

傳遞要經歷hitTest,PointInside 等方法遍歷控制元件、定位點的位置

響應要經歷nextResponder 方法將父級控制元件們串聯起來進行反饋

其中涉及的很多原理還是實際操作起來更易懂,這裡就不在多提了。

往下開始結合程式碼及日誌講一講UIButton這個特殊的UIView控制元件在點選,響應反應的背後

到底發生了什麼


 

在一切的開頭,那麼肯定得建立一個UIButton對吧,這裡簡單附上一個方法建立xgButton物件

- (void)createButton{
     _xgButton = [[XgButton alloc] initWithFrame:CGRectMake(100, 100, 20.f, 20.f)];
    [_xgButton setBackgroundColor:[UIColor redColor]];
    
    [_xgButton addTarget:self action:@selector(action) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_xgButton];    
}

- (void)action { NSLog(@"點選事件觸發"); }

在Button新增到當前view前綁定了一個單擊事件,點選時相應action方法。

因為是觸控的緣故,所以在XgButton中每個touch方法都列印NSLog(@"%s",__func__);檢視當前執行順序。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%s",__func__);
    [super touchesBegan:touches withEvent:
event]; } - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"%s",__func__); [super touchesEnded:touches withEvent:event]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"%s",__func__); [super touchesMoved:touches withEvent:event]; } - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"%s",__func__); [super touchesCancelled:touches withEvent:event]; }

當一切準備就緒後,一切都不明瞭的情況下,當然是先執行一下程式點選一下xgButton檢視下日誌到底怎麼說吧

2018-12-14 01:16:44.422578+0800 03-Button_Class[31004:2452161] -[XgButton touchesBegan:withEvent:]
2018-12-14 01:16:44.424209+0800 03-Button_Class[31004:2452161] -[XgButton touchesMoved:withEvent:]
2018-12-14 01:16:44.429849+0800 03-Button_Class[31004:2452161] -[XgButton touchesEnded:withEvent:]
2018-12-14 01:16:44.430500+0800 03-Button_Class[31004:2452161] 點選事件觸發

咦,在單擊事件方法action觸發前,Button需要經過touch事件的判斷,是否完成當前的控制器事件(ControlEvents)。

當前我們設定的是TouchUpInside,是當我們點選結束後才會響應事件。那如果點選結束TouchesEnd方法裡的

[super touchesEnded:touches withEvent:event];

註釋了,是不是就無法觸發單擊事件方法了呢?

驗證一下說辭,先把touchesEnded中的傳遞方法註釋了先。然後我們執行下程式驗證下結果

2018-12-14 01:23:49.814269+0800 03-Button_Class[31063:2461947] -[XgButton touchesBegan:withEvent:]
2018-12-14 01:23:49.860960+0800 03-Button_Class[31063:2461947] -[XgButton touchesMoved:withEvent:]
2018-12-14 01:23:49.861451+0800 03-Button_Class[31063:2461947] -[XgButton touchesEnded:withEvent:]

結果是打印出來了,但是很明顯action事件無法響應了。這說明響應鏈斷了。當前的Button無法通過touchesEnded方法判斷自身是否被點選結束了的事實。

所以無法觸發action事件。

這說明UIButton在反饋自身被點選的過程中,需要經過touch事件的確定,確定自身是否達到了ControlEvent的要求,比方說本例子中的Button繫結的是單擊按鈕,鬆開後。Button能夠反饋出與ControlEvent相同的結果時,向控制器證明了當前操作成功了。

以下是小劇場

Button:我被成功的點選了!可以根據這個結果進行正確的反饋了。我的控制器!

控制器:好嘞我知道了!這就給你顆糖

那麼反饋不出相同結果時呢?

Button:*(嗚嗚嗚嗚) - 啞巴狀態

控制器:你不出聲,我可給不了你糖果哦溜了溜了

其他的ControlEvent型別也是一樣的。

 


小總結一下

眾所周知,當觸控事件發生的時候,事件的傳遞鏈是自上而下遍歷控制元件找到了這個button。

而UIButton被點選響應的背後,touch方法群體正在辛勤的工作。通過touch方法執行的結果的反饋。來判斷當前Button是否被響應

這裡就簡而要之的講一講,不足之處往後改進!