Delegation

UITextField

- (void)loadView
{
    CGRect frame = [UIScreen mainScreen].bounds;
    BNRHypnosisView *backgroundView = [[BNRHypnosisView alloc] initWithFrame:frame];

    CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
    UITextField *textField = [[UITextField alloc] initWithFrame:textFieldRect];

    // Setting the border style on the text field will allow us to see it more easily
    textField.borderStyle = UITextBorderStyleRoundedRect;
    [backgroundView addSubview:textField];

    self.view = backgroundView;
}

UIResponder

UIResponder is an abstract class in the UIKit framework. It is the superclass of three classes that you have already encountered:

  • UIView
  • UIViewController
  • UIApplication

UIResponder是個(gè)抽象類,UIView,UIViewController和UIApplication都實(shí)現(xiàn)了此類。

UIResponder defines methods for handling (or “responding to”) events: touch events, motion events (like a shake), and remote control events (like pausing or playing). Subclasses override these methods to customize how they respond to events.

UIResponder定義了事件響應(yīng)方法,響應(yīng)touch, motion, remote control事件,其子類可以重寫這些事件響應(yīng)方法。

With touch events, it is obvious which view the user has touched. Touch events are sent directly to that view.

What about the other types of events? The UIWindow has a pointer called firstResponder which indicates who should respond to the other types of events. When you select a text field, for example, the window moves its firstResponder pointer to that text field. Motion and remote control events are sent to the first responder.

touch事件會(huì)直接發(fā)送給被觸摸的視圖。
UIWindow中有個(gè)指針叫firstResponder,來指明誰來響應(yīng)motion, remote control事件。當(dāng)選中一個(gè)text field,firstResponder指針會(huì)指向這個(gè)text field。

When a text field or a text view becomes firstResponder, it shows its keyboard. When it loses first responder status, it hides its keyboard. If you want one of these views to become first responder, you send it the message becomeFirstResponder and the keyboard appears. When you want to hide the keyboard, you send it the message resignFirstResponder.

當(dāng)text filed變成firstResponder,會(huì)顯示鍵盤,當(dāng)其不再是firstResponder,鍵盤隱藏。
如果想讓某視圖變成firstResponder,可以調(diào)用該視圖的becomeFirstResponder,反之調(diào)用resignFirstResponder

Keyboard

The keyboard’s appearance is determined by a set of the UITextField’s properties called UITextInputTraits.

property description
autocapitalizationType This determines how capitalization is handled. The options are none, words, sentences, or all characters.
autocorrectionType This will suggest and correct unknown words. This value can be YES or NO.
enablesReturnKeyAutomatically This value can be YES or NO. If set to yes, the return key will be disabled if no text has been typed. As soon as any text is entered, the return key becomes enabled.
keyboardType This determines the type of keyboard that will be displayed. Some examples are the ASCII keyboard, email address keyboard, number pad, and the URL keyboard.
secureTextEntry Setting this to YES makes the text field behave like a password field, hiding the text that is entered.
- (void)loadView
{
    CGRect frame = [UIScreen mainScreen].bounds;
    BNRHypnosisView *backgroundView = [[BNRHypnosisView alloc] initWithFrame:frame];

    CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
    UITextField *textField = [[UITextField alloc] initWithFrame:textFieldRect];

    // Setting the border style on the text field will allow us to see it more easily
    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.placeholder = @"Hypnotize me";
    // 設(shè)置鍵盤的retrun key type為Done
    // 鍵盤的return key:鍵盤輸入完成后,點(diǎn)擊return key完成輸入,隱藏鍵盤
    textField.returnKeyType = UIReturnKeyDone;

    [backgroundView addSubview:textField];
    self.view = backgroundView;
}

Delegation pattern

You have already seen the Target-Action pattern. This is one form of callbacks that is used by UIKit: When a button is tapped, it sends its action message to its target.

A button’s life is relatively simple. For objects with more complex lives, like a text field, Apple uses the delegation pattern.

代理模式,為UITextField對(duì)象設(shè)置代理,由代理來處理UITextField的各種消息。

代理要為text filed對(duì)象實(shí)現(xiàn)的一些方法如下:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
- (BOOL)textFieldShouldClear:(UITextField *)textField;
- (BOOL)textFieldShouldReturn:(UITextField *)textField;

設(shè)置text filed的delegate屬性,指定其代理

 // BNRHypnosisViewController
- (void)loadView
{
    CGRect frame = [UIScreen mainScreen].bounds;
    BNRHypnosisView *backgroundView = [[BNRHypnosisView alloc] initWithFrame:frame];

    CGRect textFieldRect = CGRectMake(40, 70, 240, 30);
    UITextField *textField = [[UITextField alloc] initWithFrame:textFieldRect];

    // Setting the border style on the text field will allow us to see it more easily
    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.placeholder = @"Hypnotize me";
    // 設(shè)置鍵盤的retrun key type為Done
    textField.returnKeyType = UIReturnKeyDone;

    // 為text filed設(shè)置delegate
    textField.delegate = self;

    [backgroundView addSubview:textField];
    self.view = backgroundView;
}

Protocol

代理需要為被代理對(duì)象實(shí)現(xiàn)哪些方法呢?這由protocol來定義,protocol就像JAVA中的接口。

The protocol for UITextField’s delegate looks like this:

// The NSObject in angled brackets refers to the NSObject protocol and tells us 
// that UITextFieldDelegate includes all of the methods in the NSObject protocol.
@protocol UITextFieldDelegate <NSObject>

@optional
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
- (void)textFieldDidBeginEditing:(UITextField *)textField;
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
- (void)textFieldDidEndEditing:(UITextField *)textField;
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
- (BOOL)textFieldShouldClear:(UITextField *)textField;
- (BOOL)textFieldShouldReturn:(UITextField *)textField;

@end

Note that a protocol is not a class; it is simply a list of method declarations.

Methods declared in a protocol can be required or optional. By default, protocol methods are required. If a protocol has optional methods, these are preceded by the directive @optional.

Before sending an optional message, the object first asks its delegate if it is okay to send that message by sending another message, respondsToSelector:. Every object implements this method, which checks at runtime whether an object implements a given method. You can turn a method selector into a value that you can pass as an argument with the @selector() directive. For example, UITextField could implement a method that looks like this:

- (void)clearButtonTapped
{
    // textFieldShouldClear: is an optional method, so we check first
    SEL clearSelector = @selector(textFieldShouldClear:);
    // 先檢查對(duì)應(yīng)的方法是否存在,如果存在再調(diào)用
    if ([self.delegate respondsToSelector:clearSelector]) {
        if ([self.delegate textFieldShouldClear:self]) {
            self.text = @"";
        }
    }
}

protocol不是一個(gè)類,只是聲明了一些抽像方法。
protocol中的方法默認(rèn)是required,就是代理必須要實(shí)現(xiàn)的;可以用@optional來聲明為可選的。
被代理的對(duì)象在調(diào)用protocol中聲明的optional方法前,會(huì)先通過respondsToSelector:方法來確認(rèn)代理是否實(shí)現(xiàn)了對(duì)應(yīng)的optional message(OC中叫message,可以理解為java中的method)。

**
對(duì)象,代理(delegate),協(xié)議(protocol),這三者的關(guān)系要理清楚:對(duì)象(比如一個(gè)text field)有一個(gè)對(duì)應(yīng)的protocol,用來定義text field對(duì)象的delegate應(yīng)該實(shí)現(xiàn)的方法,delegate要去實(shí)現(xiàn)protocol中定義的方法。text field對(duì)象會(huì)去調(diào)用delegate中實(shí)現(xiàn)的方法。
**

But for the compiler to know to check for implementations of a protocol’s required methods, the class must explicitly state that it conforms to a protocol. This is done either in the class header file or the class extension: the protocols that a class conforms to are added to a comma-delimited list inside angled brackets in the interface declaration.

delegate要標(biāo)明實(shí)現(xiàn)哪些protocol,可以頭文件或是在class extension中聲明實(shí)現(xiàn)的protocol,用尖括號(hào)括起來,如果有多個(gè)protocol用逗號(hào)分隔。

在頭文件和class extension中的區(qū)別如之前講到的,頭文件中的是public的,class extension中的是private的。

The reason for adding it to the class extension rather than the header file is the same reason as always: add to the class extension if the information (conforming to a particular protocol in this case) does not need to be publicly visible, and add it to the header file if other objects do need to know about the information.

以下是在class extension中標(biāo)明:

@interface BNRHypnosisViewController () <UITextFieldDelegate>
@end

Motion Effects

蘋果設(shè)備上,在首頁傾斜屏幕,可以看到首頁的圖標(biāo)會(huì)移動(dòng)。這可以通過UIInterpolatingMotionEffect來實(shí)現(xiàn):

UIInterpolatingMotionEffect *motionEffect;

motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[messageLabel addMotionEffect:motionEffect];

motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[messageLabel addMotionEffect:motionEffect];

main() and UIApplication

iOS應(yīng)用的程序入口,如下:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([BNRAppDelegate class]));
    }
}

The function UIApplicationMain creates an instance of a class called UIApplication. For every application, there is a single UIApplication instance. This object is responsible for maintaining the run loop. Once the application object is created, its run loop essentially becomes an infinite loop: the executing thread will never return to main().

UIApplicationMain 方法創(chuàng)建了一個(gè) UIApplication 實(shí)例,一個(gè)應(yīng)用只有一個(gè)此實(shí)例,負(fù)責(zé)維護(hù)應(yīng)用的run loop。

Another thing the function UIApplicationMain does is create an instance of the class that will serve as the UIApplication’s delegate. Notice that the final argument to the UIApplicationMain function is an NSString that is the name of the delegate’s class. So, this function will create an instance of BNRAppDelegate and set it as the delegate of the UIApplication object.

UIApplicationMain 方法不僅創(chuàng)建了UIApplication 實(shí)例,還會(huì)為其創(chuàng)建對(duì)應(yīng)的delegate,UIApplicationMain 方法的最后一個(gè)參數(shù)就是delegate's name。

The first event added to the run loop in every application is a special “kick-off” event that triggers the application to send a message to its delegate. This message is application:didFinishLaunchingWithOptions:. You implemented this method in BNRAppDelegate.m to create the window and the controller objects used in this application.

然后application調(diào)用其代理的application:didFinishLaunchingWithOptions:方法來完成窗口及相應(yīng)視圖的創(chuàng)建,我們?cè)诖朔椒ㄌ砑幼约旱囊晥D。


本文是對(duì)《iOS Programming The Big Nerd Ranch Guide 4th Edition》第七章的總結(jié)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 11,036評(píng)論 0 23
  • 大家好,我是IT修真院北京總院第24期的學(xué)員,一枚正直純潔善良的web程序員 今天給大家分享一下,修真院官網(wǎng)css...
    我是一只北極熊啊閱讀 6,070評(píng)論 0 3
  • 對(duì)于生活,愿我們不再蹉跎、不作妄談 ??梢园l(fā)有千種期許,但也要播種一個(gè)開端;不發(fā)狠、也不看穿 。不去苦求同路與照看...
    汽球閱讀 314評(píng)論 0 0
  • 忘了從什么時(shí)候起,周杰倫開始走進(jìn)我的生活。我從來沒有像那些瘋狂的粉絲一樣,把他的海報(bào)貼滿整個(gè)房間,把他的每張專輯放...
    笑容女王閱讀 883評(píng)論 0 6
  • 我 現(xiàn)在許個(gè)愿 每天早晨起床就能聞見你煮的愛心dumplings 我 現(xiàn)在許個(gè)愿 每天中午回來就能嘗見你燒的紅燒m...
    Eternity698閱讀 214評(píng)論 0 2

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