protocol(协议) 和 delegate(委托)也叫(代理)---辨析
protocol和delegate完全不是一回事。協議(protocol),(名詞)要求。就是使用了這個協議后就要按照這個協議來辦事,協議要求實現的方法就一定要實現。委托(delegate),(動詞)助手。顧名思義就是委托別人辦事,就是當 一件事情發生后,自己不處理,讓別人來處理。舉個淺顯的例子:我上班的工作主要內容包括 (1)寫代碼(2)寫文檔(3)測試程序(4)接電話(5)會見客戶。(1)(2)我自己全權負責,但是后面(3)(4)(5)我不想或者不方便自己做,所以我想找個助手(delegate)幫我做這些事,于是我定了一個招聘要求(Protocol),里寫明我的助手需要會做(3)(4)(5)這三件事。很快,我招到一個助手。即:我.delegate = 助手; 于是以后每當我遇到需要測試程序或者接電話的活,我就把他轉交給助手(delegate)去處理,助手處理完后如果有處理結果(返回值)助手會告訴我,也許我會拿來用。如果不需要或者沒有結果,我就接著做下面的事。。protocol和java里interface的概念類似,是Objective-C語法的一部分。 定義protocol如下 C代碼 @protocol ClassADelegate - (void)methodA; - (void)methodB; @end 那么就是定義了一組函數,這組函數放在一起叫作一個protocol,即 協議。函數是需要被實現的,所以如果對于class如下@interface ClassB <ClassADelegate> { } @end 就叫作ClassB conform(遵守)to protocol ClassADelegate,也就是說ClassB實現了這個協議, 也就是實現了這一組函數。有了上面這個頭文件,我們就可以放心作調用 C代碼 ClassB *b = [[ClassB alloc] init]; [b methodA]; [b methodB]; 而不用擔心出現unrecognized selector sent to instance這種錯誤了。所以protocol就是一組函數定義,是從類聲明中剝離出來的一組定義。 C代碼 id<ClassADelegate> b = ...; (把實現類對象 賦值給 遵守此協議的擁有者 b ) [b methodA]; 這種用法也常見,b是一個id類型,它知道ClassADelegate這組函數的實現(即把實現類的對象賦值給b)。那么delegate是什么?其實和protocol沒有關系。Delegate本身應該稱為一種設計模式。 是把一個類自己需要做的一部分事情,讓另一個類(也可以就是自己本身)來完成。 比如ClassC C代碼 @interface ClassC { id delegate; } @end 那么ClassC的實現(.m文件)里就可以用delegate這個變量了。 當然這里完全可以用其它名字而不是delegate。我們也可以這樣寫 C代碼 @interface ClassC { ClassB *delegate; } @end 這樣我們知道了delegate是一個ClassB,它就可以提供ClassB里的方法。 可以把一部分ClassC里的工作放在ClassB里去實現。 這樣的寫法看起來是不是有點奇怪?或者應該寫成這樣? C代碼 @interface ClassC { ClassB *classB; } @end … delegate沒有了… 所以說其實delegate只是一種模式,大家約定俗成,當把自己內部一部分實現暴露給另外一個類去做的時候,就叫實際做事的類為delegate(即助手)。為什么會需要把內部實現提出來給另一個類做呢? 最常見的目的就是為了在隱藏實現的前提下,提供一個自定義的機會。 比如Apple提供的iOS SDK里就有眾多的delegate,比如最常用的UITableView, 我們沒法知道Apple怎么重用UITableViewCell,怎么處理UITableView里Cell的增加、刪減,因為我們沒有源碼。 但是我們可以通過實現Delegate的方法來控制一個UITableView的一些行為。(即把delegate方法實現) UITableViewDataSource其實和delegate是一樣一樣的,只是由于意義不同換了個名字罷了。protocol在此扮演了什么角色呢? protocol是一種語法,它提供了一個很方便的、實現delegate模式的機會。 比如寫UITableView的時候,Apple這么干UITableView.m C代碼 - (void)doSomething { [self blahblah]; [self.delegate guruguru]; [self blahblah]; } delegate是我們寫的類,這個類如果可以被傳給UITableView做為其delegate,那唯一要求,就是它實現了 - (void)guruguru; 這個方法。如果我們把這個方法定義在一個protocol里 C代碼 @protocol XXXProtocol - (void)guruguru; @end 就說明了,UITableView需要的delegate是一個conform to XXXProtocol的類。 這就正好是id<XXXProtocol> 表達的意思。 無論具體的類是什么,它還有其它什么方法,只要它conform to這個protocol, 就說明它可以被傳給UITableView,作為它的delegate。那么Apple為了讓我們知道這個protocol是delegate需要conform的protocol, 它就把XXXProtocol改成了UITableViewDelegate這樣我們看到protocol的名字里有Delegate,就知道這個protocol里的函數是用來做自定義(Customization)的了。來源:http://haoxiang.org/2011/08/ios-delegate-and-protocol/Protocol 的其它問題1. 使用時為什么要加上 iOS.delegate = self物件名稱.delegate = self,是在採用任何協定時 一定會看到的一行程式碼,由于定義協定的類別并不需要實作協定內的方法,因為實作的部份是由採納協定的類別來實作,但是它又必須要知道是由哪一個類別來實作,因此我們必須要把採納協定類別的 instance 交給定義協定的類別,讓它來使用。 另一方面并不是任何類別都可以將 instance 傳給定義協定的類別來使用,其原因是,我們在定義此協定的類別里有宣告 delegate 變數時,有限定它必須要採納此協定(id delegate)如果沒有採用該協定就將 instance 傳給定義該協定的類別,Xcode 同樣會發出警告訊息。2. 為什么協定的生效位置不能寫在建構式中協定的生效位置寫在建構式中,并不會造成程式編譯上的任何問題,因為這是屬于邏輯上的錯誤,協定要正常生效它必須要知道實作它方法的類別的 instance,如果將生效的位置寫在建構式中,在建立定義此協定的形態的變物件時,它的確會去觸發此協定內的方法,但是由于并沒有給它實作此協定方法類別的 instance,因此不會有任何效果產生,反之,如果一定要將生效的位置寫在建構式中,那么在初始化時就必須要設定好 delegate 才行,也就是使用初始化的方法函式里還必須要帶入一個參數物件好指定給 delegate。3. 在定義協定時同時也可以採用其他的協定如果在定義協定時同時又採用其他的協定,這會導致之后採納此協定的類別,它必須同時實作出兩個協定內的方法,同樣地,你也可以利用此方式來擴充那些已經存在的協定。 C代碼 @protocol FurnaceDelegate <其它可能的協定名稱> 4. 使用 @optional 提供選擇性的實作@optional,如同它字面上的意義,在 @optional 之后的方法都可以是選擇性的實作,在定義協定時使用此方法,可以讓之后採納此協定的類別不一定要完全實作出協定內的所有方法。 C代碼 @protocol FurnaceDelegate - (void)whenCalledDelegeteFunction; @optional -(void)optionalDelegeteFunction; @end
delegate ?protocol 是objective-c 語法的一部分 但他們兩個卻完全不是一回事。主要是我們經常在同一個文件里見到這兩個東西
protocol(協議)我的理解就是定義這么一個東西。以后就按這里的規定來辦事。
delegate(委托) ?就是把事情委托給別人去辦?
@required 就是必須去辦的。比如UITableView ?delegate里面的:
-(NSInteger)tableView:(UITableView?*)tableView numberOfRowsInSection:(NSInteger)section
這個就是必須要實現的方法
@optional則是可做或不做。比如TUIableView ?delegate 里面的:
-(void)tableView:(UITableView?*)tableView didSelectRowAtIndexPath:(NSIndexPath?*)indexPath
這個就是可要可不要
?
關于delegate ?protocol 網上有一個例子講的非常形象:
? ? ? ? ? ?我上班的工作主要內容包括 (1)寫代碼(2)寫文檔(3)測試程序(4)接電話(5)會見客戶
(1)(2)我自己全權負責,但是后面(3)(4)(5)我不想或者不方便自己做,所以我想找個助手(delegate)幫我做這些事,于是我定了一個招聘要求(Protocol),里寫明我的助手需要會做(3)(4)(5)這三件事。很快,我招到一個助手。
? ? ? ? 即:我.delegate = 助手;
于是以后每當我遇到需要測試程序或者接電話的活,我就把他轉交給助手(delegate)去處理,助手處理完后如果有處理結果(返回值)助手會告訴我,也許我會拿來用。如果不需要或者沒有結果,我就接著做下面的事。。
下面實現一個簡單的protocol?
在DelegateTest.h里實現protocol?
//定義protocol 協議 #import <UIKit/UIKit.h>@protocol DelegateTestDelegate; @interface DelegateTest : NSObject {id<DelegateTestDelegate> delegate; } @property(nonatomic,assign)id<DelegateTestDelegate> delegate; @property(nonatomic,assign)NSInteger nb; -(void)printPublic; //公開 @end//協議里的方法 @protocol DelegateTestDelegate<NSObject>-(void)print:(NSInteger)number; //如果別的類也用到了這個protocol 那么就可以直接調用了。 -(void)print; @endDelegateTest.m 文件
#import "DelegateTest.h"@interface DelegateTest ()@end@implementation DelegateTest @synthesize delegate; @synthesize nb;//如果這個類是基于UIControllView的話。可以直接在ViewDidLoad里面調用。那么效果也是一樣的 這里就相當于別的類里調用這個方法。起到激活的作用 -(void)printPublic {[delegate print];[delegate print:nb]; }@end?
ViewController.h 文件
#import <UIKit/UIKit.h> #import "DelegateTest.h" @interface ViewController : UIViewController<DelegateTestDelegate> //這里的DelegateTestDelegate也就相當于UITableView里的UITableViewDelegate {DelegateTest *delegateTest; }@property (nonatomic, assign)DelegateTest *delegateTest; @endViewController.m?文件
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController @synthesize delegateTest;- (void)viewDidLoad {[super viewDidLoad];delegateTest = [[DelegateTest alloc]init];[delegateTest setDelegate:self]; //設置代理[delegateTest printPublic ]; //選擇調用delegateTest 里的這個方法。然后就可以調用下面的print了。也就相當于把print給激活了// Do any additional setup after loading the view, typically from a nib. }- (void)viewDidUnload {[super viewDidUnload];// Release any retained subviews of the main view. }//調用DelegateTest protocol 里面的方法 -(void)print {NSLog(@"qingjoin print succeed"); } -(void)print:(NSInteger)number {NSLog(@"%d",number); }- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); }@end 實現協議的步驟1? ? //delegate,遵守協議
? ? //1, 定義協議擁有者:說明delegate對象是MaryProtocol類型的協議
? ? id <MaryProtocol>? delegate;//讓擁有者(使用者) 遵守協議(先定義)
?
? ? //2,賦值協議擁有者:將當前對象 賦值 給協議擁有者
? ? delegate = curDelegate;
?
轉載于:https://www.cnblogs.com/iOS-mt/p/4103218.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的protocol(协议) 和 delegate(委托)也叫(代理)---辨析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LiDAR点云数据及其处理
- 下一篇: 性能报告之路由器性能benchmark评