蘋果的官方文檔給了很清晰的解釋:
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of 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 in one central object.
意譯一下就是:代理是一種簡單而功能強大的設計模式,這種模式用于一個對象“代表”另外一個對象和程式中其他的對象進行互動。 主對象(這裡指的是delegating object)中維護一個代理(delegate)的引用并且在合适的時候向這個代理發送消息。這個消息通知“代理”主對象即将處理或是已經處理完了某一個事件。這個代理可以通過更新自己或是其它對象的UI界面或是其它狀态來響應主對象所發送過來的這個事件的消息。或是在某些情況下能傳回一個值來影響其它即将發生的事件該如何來處理。代理的主要價值是它可以讓你容易的定制各種對象的行為。注意這裡的代理是個名詞,它本身是一個對象,這個對象是專門代表被代理對象來和程式中其他對象打交道的。
Cocoa Touch架構裡大量使用了代理這種設計模式,在每個UI控件類裡面都聲明了一個類型為id的delegate或是dataSource,檢視Cocoa的頭檔案可以發現很多如下的屬性:
@property(nonatomic, assign)id<UIActionSheetDelegate> delegate; // weak reference
通常格式為@property(nonatomic, assign)id<protocol_name> delegate; 即這個代理要遵循某一個協定,也就是說隻有遵循了這個協定的類對象才具備代理資格。這同時也要求了代理類必須在頭檔案中聲明遵循這個protocol_name協定并實作其中的@required方法,@optional的方法是可選的。
以UIActionSheet為例,我們定義一個View,當點選這個View中的某一個按鈕時觸發UIActionSheet, 當使用者對UIActionSheet完成了某一項操作,比如Destruct按鈕被按下,或是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 // telling this class(ViewController) to implement UIActionSheetDelegate
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中的方法:
#pragma mark --UIActionSheet delegate methods
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
self.myTextFromActionSheet.text = @"Action Destructed!";
break;
case 1:
self.myTextFromActionSheet.text = @"Action Button 1 Clicked!";
case 2:
self.myTextFromActionSheet.text = @"Action Button 2 Clicked!";
case 3:
self.myTextFromActionSheet.text = @"Cancel Button Clicked!";
default:
}
上面的幾步我們完成了對Cocoa中UIActionSheet已有代理的運用。然而我們很多時候需要自己編寫定制的代理,該如何實作呢?
我們要做的是,建立一個view,自定義一個代理實作更新這個view中的字元串。上面我們已經建立好了一個tab工程,借用裡面的second view。我們拖一個按鈕到上面命名為ChangeText,響應函數為- (IBAction)changeText:(id)sender;點選這個按鈕進入一個modal view 名為ChangeTextView,我們在ChangeTextView中輸入一個字元串并在退出這個view後把這個字元串更新到second view上面。如何實作modal view和second view之間的資料傳遞呢?那就是代理!誰的代理?ChangeTextView的代理!因為我們直接在ChangeTextView中輸入資料,需要由代理把輸入的字元串回報到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 {
//Is anyone listening
if([delegate respondsToSelector:@selector(textEntered:)])
{
//send the delegate function with the amount entered by the user
[delegate textEntered:textEntered.text];
[self dismissModalViewControllerAnimated:YES];
[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];
//Assign this class to the delegate of ChangeTextViewController,
//remember to make thie ViewController confirm to protocol "ChangeTextViewDelegate"
//which is delared in file ChangeTextViewController.h
CTViewController.delegate = self;
[self presentModalViewController:CTViewController animated:YES];
注意,CTViewController.delegate = self;這句實作了SecondViewController成為ChangeTextViewController對象的代理。
如何聯系我:【萬裡虎】www.bravetiger.cn
【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)
【部落格】http://www.cnblogs.com/kenshinobiy/