Objective-C 委托全方位解读

查看源码

Delegate是运用Objective-C的运行时来实现的一种设计模式。

官方文档的描述位置:

iOS Library- > General- > Cocoa Fundamentals Guide- > Cocoa Design Patterns- > How Cocoa Adapts Design Patterns- > Decorator- > Delegation


你看文档给出的位置就可以知道它的大概作用了,它是装饰器的一种实现。如果你熟悉设计模式的话,可以知道装饰器是动态实现给一个对象添加一些额外职责的设计模式。如果不是很清楚的话,请google 装饰器 设计模式 或者 Design Patterns Decorator,了解更多。


那具体到Objective-C里,Delegate就是利用Objective-C 的运行时(Runtime)来实现动态的判断某对象是否存在,某对象是否实现了一些选择器(Selector),如果实现了,则通过调用该对象的某一选择器来帮助自己实现一些功能。


在实际使用当中,设计一个自己的类Class的AClassDelegate可以通过两种方式实现,一种是非正式协议,Informal Protocol。


正式协议,Protocol。比较新的类的设计都会使用Protocol是定义自己的Delegate方法,并为之标记可选还是必需实现。

当一个类会作为另一个类的Delegate的时候,需要实现该Delegate的Protocol,这意味着如果有标记@required的相应方法,那该类的实例必需实现该方法。@optional的方法就并不一定要实现。


举一个具体的例子:

UINavigationController的Delegate应该是很少用到的,我看了一下也应该是比较简单的Delegate的设计。


[cc lang=”c”]

@protocol UINavigationControllerDelegate NSObject >


@optional


// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.

- (void)navigationController:(UINavigationController )navigationController willShowViewController:(UIViewController )viewController animated:(BOOL)animated;

- (void)navigationController:(UINavigationController )navigationController didShowViewController:(UIViewController )viewController animated:(BOOL)animated;


@end

[/cc]


这个Delegate的方法都是可选实现的,不是必须的,所以通常大家比较少去主动用。

那分析一下这个Delegate,我们可以知道,这个Delegate的设计是UINavigationController在show某一个ViewController的时候会对它的Delegate进行一种类似通知的调用:“我即将展示某某ViewController了”,

那该Delegate可以通过实现这个方法进行相应的操作。


举一个具体实现的例子

[cc lang=”c”]

// AZDelegationDemo.h

// Created by Aladdin Zhang on 8/24/11.


#import

@protocol AZDelegationDemoDelegate;

@interface AZDelegationDemo : NSObject{

idAZDelegationDemoDelegate > delegate;

NSMutableArray * shoppingList;

}

@property (nonatomic,assign) idAZDelegationDemoDelegate > delegate;

@end


@interface AZDelegationDemo (informal_protocol_delegate)

- (void)buyCoffee;

@end


@protocol AZDelegationDemoDelegate NSObject >

@required

- (void)buyPork;

@optional

- (void)buyMilk;

@end


// AZDelegationDemo.m

// Created by Aladdin Zhang on 8/24/11.


#import “AZDelegationDemo.h”


@implementation AZDelegationDemo

@synthesize delegate;

- (id)init{

self = [super init];

if (self) {

shoppingList = [NSMutableArray arrayWithCapacity:20];

}

return self;

}

- (void)buyStuff{

NSLog(@”My Shopping List %@”,shoppingList);

}

- (void)weeklyShopping{

if (self.delegate&&[self.delegate conformsToProtocol:@protocol(AZDelegationDemoDelegate)]) {

[self.delegate performSelector:@selector(buyPork)];

if ([self.delegate respondsToSelector:@selector(buyMilk)]) {

[self.delegate performSelector:@selector(buyMilk)];

}else{

[shoppingList addObject:[NSString stringWithFormat:@”Milk”]];

}

if ([self.delegate respondsToSelector:@selector(buyCoffee)]) {

[self.delegate performSelector:@selector(buyCoffee)];

}else{

[shoppingList addObject:[NSString stringWithFormat:@”Coffee”]];

}

[self buyStuff];

}

}

@end

[/cc]

这是我刚刚为这个回答写的一个例子,基本上涵盖了一般用途的Delegate的设计,这里不对具体Delegate的实现进行说明了,和其他系统提供的Delegate的使用基本一致。

在这个例子中,我分别使用了分类(Category),即非正式协议,和协议(Protocol)来实现Delegate的设计。其实运用Objective-C的动态性,分类实现的协议和Protocol中的可选的协议方法,在调用上是一样的。使用正式协议,并标记为必需的好处是,可以通过编译器来帮助矫正不该出现的错误。


来自知乎