委托(delegate)也叫代理是ios开发中常用的而设计模式。我们借助于protocol可以很方便的实现这种设计模式。
什么是代理
苹果官方文档给了很清晰的解释:
Delegation is a sample and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegatin object keeps a reference to the other object-the delegate-and at the appropriate time sends a message to it. The message infoms the delegateof an event that the delegating object is about to handle or has just handled. The delegate may responds to the message by updating the appearance or state fo itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects how an impending event is handled. The main value of delegation is that it allows yhou to easily customize the behavior of several objects in one central object.
意译:
代理是一种简单而功能强大的设计模式。这种模式用于一个对象代表另外一个对象和程序中其他的对象进行交互。主对象中维护一个代理的引用并且在合适的时候向这个代理发送消息。这个消息通知代理主对象即将处理或是已经处理完了某一个事件。这个代理可以通过更新自己或是其他对象的UI 界面或是其他状态来响应主对象所发过来的的这个事件的消息。或是在某些情况下能返回一个值来影响其他即将发生事件该如何来处理。代理的主要价值是它可以让你容易的定制各种对象的行为。注意这里的代理是个名词。它本身是一个对象。这个对象时专门代表被代理对象来和程序中其他对象打交道的。
Cocoa中的代理
cocoa Touch 框架里大量使用了代理这种设置模式,在每个UI 控件类里都声明了一个类型为id的delegate或是dataSource,查看Cocoa的头文件可以发现很多如下的属性:
@property(nonatomic, assign)id<UIActionSheetDelegate> delegate; //weak reference
通常模式@property (nonatomic, assign) id<protocol_name> delegate; 即这个代理要遵循某一个协议,也就是说只有遵循了这个协议的类对象才具备资格。这同时也要求了代理类必须在头文件中声明这个protocol_name 协议并实现其中的@require 方法, @optional的方法是可选的
以UIActionSheet为例,我们定义了一个view,当点击这个view中的某一个按钮时触发UIActionSheet, 当用户对UIActionSheet完成了某一项操作,比如Destruc按钮被按下,或是cancel按钮被按下, UIActionSheet会发送消息给delegate, 由delegate完成对用户操作的响应,比如打印一个字符串到屏幕上,
首先,我们创建一个基于tab的工程, 在FirstViewController.h中添加代码,是这个类遵循UIActionSheetDelegate协议:
@interface FirstViewController : UIViewController <UIActionSheetDelegate>
在view中添加一个按钮用于触发这个ActionSheet, 然后编写这个按钮的响应代码:
- (IBAction)invokeActionSheet:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Delegate Example" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Destruct" otherButtonTitles:@"Button 1", @"Button 2", nil];
[actionSheet showInView:self.tabBarController.view];
[actionSheet release];
}
注意, 上面有一个很重要的设置就是参数中有个delegate:self, 这个设置就是指明了UIActionSheet的代理为self, 也即FirstViewController.
然后在FirstViewController.m中实现UIActionSheetDelegate中的方法:
#programa mark -- UIActionSheet delegate methods
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)butonIndex {
switch (buttonIndex) {
case 0:
self.myTextFromActionSheet.text = @"Action Destructed!";
break;
case 1;
self.myTextFromActionSheet.text = @"Action Button 1 clicked!";
break;
case 2:
self.myTextFromActionSheet.text = @"Action Button 2 clicked!";
break;
case 3:
self.myTextFromActionSheet.text = @"Cancel Button Clicked!";
break;
default:
break;
}
}
自定义代理
我们要做的是,创建一个view,自定义一个代理实现更新这个view中的字符串。 上面我们已经创建好了一个tab工程, 借用里面的second view。 我们拖一个按钮到上面命名为ChangeText, 响应函数为 - (IBAction)changeText:(id)sender;点击这个按钮进入modal view名为Change TextView, 我们在ChangeTextView中输入一个字符串并在退出这个view后面把这个字符串更新到second view上面。如何实现modal view和second view之间的数据 传递呢?那就是代理
1、创建一个新的类ChangeTextViewController,并创建相应的xib文件。
2、在ChangeTextViewController.h中声明一个协议ChangeTextViewDelegate:
@protocol ChangeTextViewDelegate <NSobject>
- (void) textEntered:(NSString *)text;
@end
和UIActionSheet类似,在ChangeTextViewController中我们也需要添加一个代理的声明:
@property (assign, nonatomic) id<ChangeTextViewDelegate> delegate;
3、我们需要在ChangeTextViewController.xib中添加一个按钮save, 当按下这个按钮会返回到second view中,并更新字符串,对save按钮的响应函数
- (IBAction)saveButtonClicked:(id)sender {
if ([delegate respondsToSelector:@selector(textEntered:)])
{
[delegate textEntered:textEntered.text];
}
[self dismissModalViewControllerAnimated:YES];
}
[delegate textEntered:textEntered.text];
[delegate textEntered:textEntered.text];这句代码的含义就是ChangeTextViewController通知代理,textEntered这个事件发生了,对textEntered这个消息的实现, 即如何响应这个textEntered的事件有代理来实现。在本例中,SecondViewController就是ChangeTextViewController对象的代理。所以我们要对SecondViewController做相应的设置使其满足代理的条件。首先,在SecondViewController.h中声明遵循协议ChangeTextViewDelegate。然后编辑ChangeText按钮的响应函数-
(IBAction)changeText:(id)sender;
- (IBAction)changeText:(id)sender {
ChangeTextViewController *CTViewController = [[ChangeTextViewController alloc] initWithNibName:@"ChangeTextViewController" bundle:nil];
CTViewController.delegate = self;
[self presentModalViewController:CTViewController animated:YES];
}
注意,CTViewController.delegate = self ;这句实现了SecondViewController成为ChangeTextViewController对象的代理