第一響應(yīng)者

第一響應(yīng)者 (The First Responder)
  什么是第一響應(yīng)者?簡單的講,第一響應(yīng)者是一個(gè)UIWindow對象接收到一個(gè)事件后,第一個(gè)來響應(yīng)的該事件的對象。注意:這個(gè)第一響應(yīng)者與觸摸檢測到的第一個(gè)響應(yīng)的UIView并不是一個(gè)概念。第一響應(yīng)者一般情況下用于處理非觸摸事件(手機(jī)搖晃、耳機(jī)線控的遠(yuǎn)程空間)或非本窗口的觸摸事件(鍵盤觸摸事件),通俗點(diǎn)講其實(shí)就是管別人閑事的響應(yīng)者。在IOS中,當(dāng)然管閑事并不是所有控件都愿意的,這么說好像并不是很好理解,或著是站在編程人員的角度來看待這個(gè)問題,程序員負(fù)責(zé)告訴系統(tǒng)哪個(gè)對象可以成為第一響應(yīng)者(canBecomeFirstResponder),如果方法canBecomeFirstResponder返回YES,這個(gè)響應(yīng)者對象才有資格稱為第一響應(yīng)者。有資格并不代表一定可以成為第一響應(yīng)者,還要becomeFirstResponder正式成為第一響應(yīng)者。同時(shí)也有對應(yīng)的canResignFirstResponder和resignFirstResponder是否可以解除第一響應(yīng)者。

值得注意的是,一個(gè)UIWindow對象在某一時(shí)刻只能有一個(gè)響應(yīng)者對象可以成為第一響應(yīng)者。我們可以通過isFirstResponder來判斷某一個(gè)對象是否為第一響應(yīng)者。

我們可以用蘋果的私有方法來獲得第一響應(yīng)者

    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    UIView *firstResponder = [keyWindow performSelector:@selector(firstResponder)];

下面我們用搖一搖事件來說一說第一響應(yīng)者響應(yīng)事件流程

代碼

在視圖控制器中
- (void)viewDidLoad {
    [super viewDidLoad];
    
    HeaderView *headerView = [[HeaderView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];

    headerView.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:headerView];
    
}

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {

    NSLog(@"~~~~~~~~~motionBegan");
    
    
    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    UIView *firstResponder = [keyWindow performSelector:@selector(firstResponder)];
    
    
}

在晃動(dòng)手機(jī)后,我們可以看到斷點(diǎn)打印的firstResponder為空。

斷點(diǎn)

此時(shí)的調(diào)用流程為:

調(diào)用流程

這個(gè)時(shí)候卻響應(yīng)了搖一搖事件,為什么呢?系統(tǒng)這個(gè)時(shí)候會(huì)找到當(dāng)前視圖,即self.view,如果self.view如果不能響應(yīng),則會(huì)依據(jù)響應(yīng)鏈找到能夠響應(yīng)該事件的響應(yīng)者,在這里self.view.nextResponse就是ViewController,所以會(huì)響應(yīng)這個(gè)搖一搖事件。

然后我們在HerderView里面加入一些代碼

@interface HeaderView ()

@end

@implementation HeaderView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
//        [self becomeFirstResponder];

    }
    return self;
}

//- (BOOL)canBecomeFirstResponder {
//
//    return YES;
//}

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {

    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    UIView *firstResponder = [keyWindow performSelector:@selector(firstResponder)];
    
}

然后搖一搖事件,發(fā)現(xiàn)HeaderView并沒有響應(yīng)搖一搖事件,而是還是由ViewController來響應(yīng)的。

然后我們將注釋的部分打開,注意這里讓HeaderView成為響應(yīng)者,注意一定要寫canBecomeFirstResponder函數(shù),不然HeaderView就算寫了becomeFirstResponder也不能成為第一響應(yīng)者,然后搖一搖可以看到HeaderView的motionBegan調(diào)用了,HeaderView響應(yīng)了這個(gè)事件,同時(shí)這個(gè)時(shí)候的第一響應(yīng)者為HeaderView,函數(shù)調(diào)用流程為:

調(diào)用流程

然后將HeaderView的motionBegan函數(shù)注釋掉,搖一搖,然后發(fā)現(xiàn)ViewController的motionBegan函數(shù)調(diào)用了,這個(gè)時(shí)候事件由第一響應(yīng)者HeaderView傳遞給了ViewController,事件的調(diào)用流程:

調(diào)用流程

在這里我們看到調(diào)用流程里有forwardMethodIntld函數(shù),推測他就是在響應(yīng)鏈中的響應(yīng)者無法響應(yīng)事件時(shí)進(jìn)行轉(zhuǎn)發(fā)到下一個(gè)響應(yīng)者的函數(shù),

在這里我們可以分析一下

  1. 在HeaderView沒有成為第一響應(yīng)者,搖一搖的時(shí)候有一個(gè)forwardMethodIntld函數(shù),這個(gè)時(shí)候由self.view進(jìn)行開始響應(yīng),但是self.view并不能響應(yīng)該事件,然后向上傳遞給ViewController,而ViewController能夠響應(yīng)事件,然后事件到這里被處理,不會(huì)繼續(xù)傳遞下去,所以進(jìn)行了一次轉(zhuǎn)發(fā)。
  2. 在HeaderView成為第一響應(yīng)者,然后也有搖一搖事件motionBegan響應(yīng)的時(shí)候,事件直接找到第一響應(yīng)者,發(fā)現(xiàn)第一響應(yīng)者能夠響應(yīng)該事件,事件到此結(jié)束,所以這里沒有forwardMethodIntld函數(shù),也就沒有進(jìn)行事件的轉(zhuǎn)發(fā)。
  3. 在HeaderView成為第一響應(yīng)者,然后沒有響應(yīng)搖一搖事件motionBegan的時(shí)候,ViewController響應(yīng)了該事件,發(fā)現(xiàn)這里有兩個(gè)forwardMethodIntld函數(shù),原因是找到第一響應(yīng)者HeaderView的時(shí)候,發(fā)現(xiàn)并不能響應(yīng)該事件,然后由響應(yīng)鏈的上一層self.view響應(yīng),self.view也不能響應(yīng)該事件,然后找到self.view的上一層,即ViewController,然后響應(yīng)該事件,所以這里進(jìn)行了兩次事件的轉(zhuǎn)發(fā)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容