什麼是代理

委託(delegate)也叫代理是iOS開發中經常使用的設計模式。咱們藉助於protocol(參考博文:objective-c協議(protocol))能夠很方便的實現這種設計模式。objective-c

什麼是代理?

蘋果的官方文檔給了很清晰的解釋:設計模式

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.app

意譯一下就是:代理是一種簡單而功能強大的設計模式,這種模式用於一個對象「表明」另一個對象和程序中其餘的對象進行交互。 主對象(這裏指的是delegating object)中維護一個代理(delegate)的引用而且在合適的時候向這個代理髮送消息。這個消息通知「代理」主對象即將處理或是已經處理完了某一個事件。這個代理能夠經過更新本身或是其它對象的UI界面或是其它狀態來響應主對象所發送過來的這個事件的消息。或是在某些狀況下能返回一個值來影響其它即將發生的事件該如何來處理。代理的主要價值是它可讓你容易的定製各類對象的行爲。注意這裏的代理是個名詞,它自己是一個對象,這個對象是專門表明被代理對象來和程序中其餘對象打交道的。框架

 

Cocoa中的代理

Cocoa Touch框架裏大量使用了代理這種設計模式,在每一個UI控件類裏面都聲明瞭一個類型爲id的delegate或是dataSource,查看Cocoa的頭文件能夠發現不少以下的屬性:函數

 

 

@property(nonatomicassign)id<UIActionSheetDelegate> delegate;   // weak referenceui

一般格式爲@property(nonatomicassign)id<protocol_name> delegate;  即這個代理要遵循某一個協議,也就是說只有遵循了這個協議的類對象才具有代理資格。這同時也要求了代理類必須在頭文件中聲明遵循這個protocol_name協議並實現其中的@required方法,@optional的方法是可選的。this

以UIActionSheet爲例,咱們定義一個View,當點擊這個View中的某一個按鈕時觸發UIActionSheet, 當用戶對UIActionSheet完成了某一項操做,好比Destruct按鈕被按下,或是cancel按鈕被按下,UIActionSheet會發送消息給delegate,由delegate完成對用戶操做的響應,好比打印一個字符串到屏幕上。圖示說明以下:atom

首先,咱們建立一個基於tab的工程,在FirstViewController.h中添加代碼,使這個類遵循UIActionSheetDelegate協議:spa

 

[cpp]  view plain copy
 
  1. @interface FirstViewController : UIViewController <UIActionSheetDelegate>  

 

 

在View中添加一個按鈕用於觸發這個ActionSheet,而後編寫這個按鈕的響應代碼:.net

 

[cpp]  view plain copy
 
  1. - (IBAction)invokeActionSheet:(id)sender {  
  2.       
  3.     UIActionSheet *actionSheet = [[UIActionSheet alloc]  
  4.                                   initWithTitle:@"Delegate Example"  
  5.                                   delegate:self // telling this class(ViewController) to implement UIActionSheetDelegate  
  6.                                   cancelButtonTitle:@"Cancel"  
  7.                                   destructiveButtonTitle:@"Destruct"  
  8.                                   otherButtonTitles:@"Button 1",@"Button 2",nil];  
  9.       
  10.     [actionSheet showInView:self.tabBarController.view];  
  11.     [actionSheet release];  
  12. }  


注意,上面有一個很重要的設置就是參數中有個delegate:self,這個設置就是指明瞭UIActionSheet的代理爲self, 也即FirstViewController。

 


而後在FirstViewController.m中實現UIActionSheetDelegate中的方法:

 

[cpp]  view plain copy
 
  1. #pragma mark --UIActionSheet delegate methods  
  2. - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {  
  3.     switch (buttonIndex) {  
  4.         case 0:  
  5.             self.myTextFromActionSheet.text = @"Action Destructed!";  
  6.             break;  
  7.         case 1:  
  8.             self.myTextFromActionSheet.text = @"Action Button 1 Clicked!";  
  9.             break;  
  10.         case 2:  
  11.             self.myTextFromActionSheet.text = @"Action Button 2 Clicked!";  
  12.             break;  
  13.         case 3:  
  14.             self.myTextFromActionSheet.text = @"Cancel Button Clicked!";  
  15.             break;  
  16.         default:  
  17.             break;  
  18.     }  
  19.       
  20. }  

 

上面的幾步咱們完成了對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上面去。

一、建立一個新的類ChangeTextViewController,並建立相應的xib文件。

二、在ChangeTextViewController.h中聲明一個協議ChangeTextViewDelegate:

 

[cpp]  view plain copy
 
  1. @protocol ChangeTextViewDelegate <NSObject>  
  2.   
  3. - (void) textEntered:(NSString*) text;  
  4.   
  5. @end  


和UIActionSheet相似,在ChangeTextViewController中咱們也須要添加一個代理的聲明:

[cpp]  view plain copy
 
  1. @property (assign, nonatomic) id<ChangeTextViewDelegate> delegate;  

 

 

三、咱們還須要在ChangeTextViewController.xib中添加一個按鈕save,當按下這個按鈕會返回到second view中,並更新字符串。對save按鈕的響應函數爲:

 

[cpp]  view plain copy
 
  1. - (IBAction)saveButtonClicked:(id)sender {  
  2.     //Is anyone listening  
  3.     if([delegate respondsToSelector:@selector(textEntered:)])  
  4.     {  
  5.         //send the delegate function with the amount entered by the user  
  6.         [delegate textEntered:textEntered.text];  
  7.     }  
  8.       
  9.     [self dismissModalViewControllerAnimated:YES];  
  10. }  

 

 

 

[delegate textEntered:textEntered.text];這句代碼的含義就是ChangeTextViewController通知代理,textEntered這個事件發生了,對textEntered這個消息的實現,即如何響應這個textEntered的事件由代理來實現。在本例中,SecondViewController就是ChangeTextViewController對象的代理。因此,咱們要對SecondViewController作相應的設置使其知足代理的條件。首先,在SecondViewController.h中聲明遵循協議ChangeTextViewDelegate。而後編輯ChangeText按鈕的響應函數- (IBAction)changeText:(id)sender;

 

[cpp]  view plain copy
 
  1. - (IBAction)changeText:(id)sender {  
  2.     ChangeTextViewController *CTViewController = [[ChangeTextViewController alloc] initWithNibName:@"ChangeTextViewController" bundle:nil];  
  3.     //Assign this class to the delegate of ChangeTextViewController,  
  4.     //remember to make thie ViewController confirm to protocol "ChangeTextViewDelegate"  
  5.     //which is delared in file ChangeTextViewController.h  
  6.     CTViewController.delegate = self;  
  7.     [self presentModalViewController:CTViewController animated:YES];  
  8. }  


注意,CTViewController.delegate = self;這句實現了SecondViewController成爲ChangeTextViewController對象的代理。

相關文章
相關標籤/搜索