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是否被響應

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM