我们来用delegate 的想法来实作前面提到的状况。

定义Protocol 与Delegate 的方式

我们先来建立一个NSButton的subclass,叫做MyButtonMyButton的delegate必须实现MyButtonDelegate这个protocol。.h文件中定义如下:

#import <Cocoa/Cocoa.h>

@class MyButton;

@protocol MyButtonDelegate
- (void)myButtonDidBecomeClicked:(MyButton *)button;
- (void)myButtonDidBecomeDoubleClicked:(MyButton *)button;
- (void)myButtonDidBecomeTripleClicked:(MyButton *)button;
- (void)myButtonDidBecomeQuadrupleClicked:(MyButton *)button;
@end

@interface MyButton : NSButton
{
    id <MyButtonDelegate> delegate;
}
@property (weak, nonatomic) id <MyButtonDelegate> delegate;
@end

逐行解释这个header 里头的内容:

  1. #import <Cocoa/Cocoa.h>:因为NSButton 是在AppKit 里头,所以我们必须调用的header。
  2. @class MyButton;:因为在我们接下来的protocol定义中,会用到MyButton这个class,但是MyButton其实是定义在MyButtonDelegate的下面,所以我们需要先预先定义MyButton这个class的存在。
  3. @protocol MyButtonDelegate开始,就是在定义MyButtonDelegate这个protocol里头的四个method。接下来定义MyButton这个class,里头有一个叫做delegate的变数。

实现Delegate Methods

假如我们有一个叫做MyController的controller实例,要成为MyButton的delegate,我们会这么做。首先是.h部分:

@interface MyController : NSObject <MyButtonDelegate>
{
    IBOutlet MyButton *myButton;
}
@end

我们要先定义MyController有实现MyButtonDelegate这个protocol,如此一来,假如MyController漏了实现哪些定义在MyButtonDelegate里头的method,在编译的时候就会跳出警告,要求我们修正,如果我们还是不实现的话,执行时,就会发生找不到selector对应的实现的错误而crash。

如果MyController又同时是其他实例的delegate的话,我们可以在这段用尖括号包起来,继续加入其他的protocol的名称,例如<MyButtonDelegate, AnotherProtocol>。至于一个实例是否有遵守某个protocol,我们可以用conformsToProtocol:检查。

MyController的实作中,我们就只要将myButton的delegate设成自己,然后实作该实作的method。我个人不太喜欢在protocol的宣告中出现大量注解,因为在实作protocol的时候,最方便的方式就是直接把protocol定义的method复制贴上,接着逐一把肉放进protocol定义的骨干里;如果当中出现注解,复制贴上之后,还要把这些注解删掉,其实很烦人。

@implementation MyController

- (void)awakeFromNib
{
    [myButton setDelegate:self];
}

#pragma mark - MyButtonDelegate

- (void)myButtonDidBecomeClicked:(MyButton *)button
{
}
- (void)myButtonDidBecomeDoubleClicked:(MyButton *)button
{
}
- (void)myButtonDidBecomeTripleClicked:(MyButton *)button
{
}
- (void)myButtonDidBecomeQuadrupleClicked:(MyButton *)button
{
}

@end

我们在这边透过setDelegate:指定delegate,如果我们把delegate宣告成是一个IBOutlet的话,也可以直接在Interface Builder中连结。

Delegate Methods 是怎么被调用的?

MyButton是怎样调用delegate 的呢?其实很简单。

@implementation MyButton

- (void)mouseDown:(NSEvent *)theEvent
{
    switch ([theEvent clickCount]) {
        case 1:
            [delegate myButtonDidBecomeClicked:self];
            break;
        case 2:
            [delegate myButtonDidBecomeDoubleClicked:self];
            break;
        case 3:
            [delegate myButtonDidBecomeTripleClicked:self];
            break;
        case 4:
            [delegate myButtonDidBecomeQuadrupleClicked:self];
            break;
        default:
            break;
    }
}

@synthesize delegate;
@end

results matching ""

    No results matching ""