事件的傳遞是從上到下(父控件到子控件),事件的響應是從下到上(順着響應者鏈條向上傳遞):子控件到父控件。ide
若是當前這個view是控制器的view,那麼控制器就是上一個響應者spa
若是當前這個view不是控制器的view,那麼父控件就是上一個響應者code
若是view 的控制器存在,就傳遞給控制器;對象
若是控制器不存在,則將其傳遞給它的父視圖blog
在視圖層次結構的最頂級視圖,若是也不能處理收到的事件或消息,則其將事件或消息傳遞給 window 對象進行處理事件
若是 window 對象也不處理,則其將事件或消息傳遞給 UIApplication 對象it
若是 UIApplication 也不能處理該事件或消息,則將其丟棄(銷燬)io
由於系統默認作法是把事件上拋給父控件,因此能夠經過重寫本身的touches方法和父控件的touches方法來達到一個事件多個對象處理的目的。event
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 1.本身先處理事件... NSLog(@"do somthing..."); // 2.再調用系統的默認作法,再把事件交給上一個響應者處理 [super touchesBegan:touches withEvent:event]; }
若是父控件不能接收觸摸事件,則子控件也沒法接收觸摸事件class
若是想讓控件不處理觸摸事件,能夠設置userInteractionEnabled = NO,結果是包括父控件在內的全部子控件都不能處理觸摸事件(雖然設置透明度和hidden=YES也能夠,可是那樣就看不見了注意:若是父控件的透明度設置爲0或者hidden=YES,那麼子控件也是不可見的。)
遍歷一個控件的子控件的順序是從上到下的(最後添加的view最早被遍歷)。
指定某一個子控件響應事件,只須要在父控件的hitTest中返回指定的子控件就能夠。
若是一個控件的isUserInteractionEnabled=false,想讓它繼續繼續處理觸摸事件,能夠在它的父控件的hitTest方法中直接返回它。
hitTest查找第一響應者的時候,即使父控件是第一響應者,仍是要調用子控件的hitTest方法,不然怎麼知道是否是還有其餘最合適的響應者
先調用父控件的point:inside:方法
調用最上面子控件的point:inside:方法
若是最上面子控件的point:inside:方法返回false,則對應的hitTest返回nil