終於苦等到了iOS項目,把PHP項目移交了。但iOS學習停滯了那么長時間大丈夫?不管了,先惡補兩天吧,能看到哪里就是哪里,然后邊做邊學。
今天學了下前台UI,就來說下響應對象(Responder Object)吧。之所以說初涉,是看到教程后面的章節還會涉及觸摸,暫時沒學到就不寫了。
1. UIResonder
對於C#里所有的控件(例如TextBox),都繼承於Control類。而Control類的繼承關系如下:
System.ComponentModel.Component
System.Windows.Forms.Control
對於iOS里的UI類,也有類似的繼承關系。
例如對於UITextField,繼承於UIControl;UIControl繼承於UIView,UIView繼承於UIResponder,UIResponder繼承於NSObject。
具體架構可以參見:
UIResponder是UIKit框架中的類(Mac OS X Cocoa對應的是AppKit框架)。
2. 第一響應對象
在應用的響應對象里,會有一個成為第一響應對象。
第一響應對象和其他響應對象之間有什么區別?對於普通的觸摸事件沒什么區別。就算我把一個按鈕設置成第一響應對象,當我點擊其他按鈕時,還是會響應其他按鈕,而不會優先響應第一響應對象。
第一響應對象的區別在於負責處理那些和屏幕位置無關的事件,例如搖動。
蘋果官方文檔的說法是:第一響應對象是窗口中,應用程序認為最適合處理事件的對象。
一個班只能有一個班長,應用的響應對象中,只能有一個響應對象成為第一響應對象。
3. 成為與取消第一響應對象。
要當第一響應對象,還需要有View來毛遂自薦:
- (BOOL) canBecomeFirstResponder
{
returnYES;
}
如果缺少了這段,就算用[view becomeFirstResponder]也不能讓一個view成為第一響應對象。。。強扭的瓜不甜?好吧不是這個原因。大多數視圖默認只關心與自己有關聯的事件,並且(幾乎)總是有機會來處理這些事件。以UIButton為例,當用戶單擊某個UIButton對象時,無論當前的第一響應對象是哪個視圖,該對象都會收到指定的動作消息。當上第一響應對象吃力不討好么。。。所以只能由某個UIResponder明確表示自己願意成為第一響應對象才行。(我不知道設計上是基於什么考慮。。。安全?)
在當上第一響應對象時,不同對象可能會有一些特殊的表現。例如UITextField當上的時候,就會調出一塊小鍵盤。
第一響應對象也有可能被辭退。發送一個resignFirstResponder,就可以勸退。
4. 第一響應對象的任務
剛才說了第一響應對象可以處理搖動。就來看個范例吧:
- (void) motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { if(motion == UIEventSubtypeMotionShake) { NSLog(@"Device is beginning to shake"); [selfsetCircleColor:[UIColorredColor]]; [selfsetNeedsDisplay]; } }
當搖動開始時觸發某些行為。
5. 獲取當前第一響應對象
提問的家伙用了如下的方式來獲取
UIView *firstResponder = [keyWindow performSelector:@selector(firstResponder)];
結果被蘋果打回來,說用了非公開的API。。。
於是這家伙只好苦逼地用遞歸了:
implementationUIView (FindFirstResponder) - (UIView *)findFirstResponder { if (self.isFirstResponder) { return self; } for (UIView *subView in self.subviews) { UIView *firstResponder = [subView findFirstResponder]; if (firstResponder != nil) { return firstResponder; } } return nil; } @end
恩。。。所以如果有必要的話,要么指定一個固定的第一響應對象,要么弄個全局變量來保存當前第一響應對象?