從開始從事OC工作到現在大概1年多了,從當初接觸oc的"協議"的不明白,到現在代碼中隨處可見的委託,協議,其中感悟頗多。
首先,大家應該都明白的是委託是協議的一種,顧名思義,就是委託他人幫自己去做什麼事。也就是當自己做什麼事情不方便的時候,就可以建立一個委託,這樣就可以委託他人幫自己去實現什麼方法。其次,我簡單的總結了一下自己用到的委託的作用有兩個,一個是傳值,一個是傳事件。1.所謂傳值經常用在b類要把自己的一個資料或者對象傳給a類,讓a類去展示或者處理。(切分緊耦合,和代碼分塊的時候經常用)2.所謂傳事件就是a類發生了什麼事,把這件事告訴關注自己的人,也就是委託的對象,由委託的對象去考慮發生這個事件後應該做出什麼反映。(這個經常見,例如在非同步請求中,介面事件觸發資料層改變等等)3.利用委託賦值,這種方法感覺是為了不暴露自己的屬性就可以給自己複值,而且這樣更方便了類的管理,只有在你想要讓別人給你賦值的時候才調用,這樣的賦值更可控一些。(例如tableView中的委託(dateSource)中常見)。最後,我想分享一下在使用委託的時候的一些心得和注意事項。心得:delegate的命名要準確,盡量看名字就知道用法。delegate和通知有的用法有些象,但是前者是單對單的,後者是單對多的情況。注意:在dealloc要把delegate至為nil,還有就是delegate設定屬性的時候要用assign,不要用retain。
委託
在IOS中委託通過一種@protocol的方式實現,所以又稱為協議.協議是多個類共用的一個方法列表,在協議中所列出的方法沒有響應的實現,由其它人來實現.這叫好比我想買個手機,所以我有個buyIphone 方法,但是我不知道誰那買手機,所以把這個需求發布出去(比如公布在網站上),如果有賣手機的商人(也就是說他能實現buyIphone這個方法)看到,他就會接受我的委託,(在商人自己的類中實現<XXXdelegate>),那麼我的委派物件就指向了這個商人..當我要買手機的時候,直接找他就行了.
例如:
@protocol MyDelegate-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money;@end@interface My : NSObject{ id<MyDelegate> deleage;}@property(assign,nonatomic)id<MyDelegate> delegate;@end
代碼中聲明了一個協議 名叫Mydelegate,在其中有一個buyIphone方法,即一個委託項。當我要購買手機的時候只需要通過delegate 調用 BuyIphone方法即可.
如下:
-(void)willbuy{ [delegate buyIphone:@"iphone 4s" money:@"4888"];}
我不必關心誰現實了這一委託,只要實現了這個委託的類,並且buyIphone是聲明的委託中必須實現的方法,那麼就一定能夠得到結果.
例如:商人類實現了這一委託(用<Mydelegate>表示實現)
#import <Foundation/Foundation.h>#import "My.h"@interface Business : NSObject<MyDelegate>@end
然後在 @implementation Business 中調用 buyIphone方法
#import "Business.h"@implementation Business-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money{ NSLog(@"手機有貨,這個價錢賣你了,發貨中!!");}@end
委託是Cocoa中最簡單、最靈活的模式之一。委託是指給一個對象提供機會對另一個對象中的變化做出反應或者影響另一個對象的行為。其基本思想是:兩個對象協同解決問題。一個對象非常普通,並且打算在廣泛的情形中重用。它儲存指向另一個對象(即它的委託)的引用,並在關鍵時刻給委託發訊息。訊息可能只是通知委託發生了某件事情,給委託提供機會執行額外的處理,或者訊息可能要求委託提供一些關鍵的資訊以控制所發生的事情。
4 天前 上傳下載附件 (18 KB) 委託方法通常包括3種動詞:should、will、did。
should表示一個動作發生前,通常帶有傳回值,可以在動作發生之前改變對象狀態。
will在動作發生前,委託可以對動作做出響應,但不帶有傳回值。
did在動作發生後做出的響應。
從方法的定義我們不難看出委託模式能夠起到兩方面的作用:
第一:委託協助對象主體完成某項操作,將需要定製化的操作通過委派物件來自訂實現,達到和子類化對象主體同樣的作用。
第二:事件監聽,委派物件監聽對象主體的某些重要事件,對事件做出具體響應或廣播事件交給需要作出響應的對象。
個人理解採用委託模式的好處在於:
1、避免子類化帶來的過多的子類以及子類與父類的耦合
2、通過委託傳遞訊息機制實現分層解耦
委託模式的實現思路:
1、通常是在對象主體包含一個委派物件的弱引用:
@interface A : NSObject
{
IBOutlet id delegate;
} -(id) delegate;
-(void) setDelegate:(id)obj;
2、委派物件的實現有兩種方式:正式協議和非正式協議,對象主體在協議中定義委託方法,委派物件可以選擇實現其中某些委託方法,因此如果通過正式協議定義委託方法需要使用@option。
@protocol NSSearchDelegate
@option
-(void)didSearchFinish:(*NSNotification) aNotification;
@end
3、連線物件主體和委託,無非就是通過setDelegate:(id)obj來實現。
4、觸發委託方法。
昨天做了一個demo,用到了簡單代理。
delegate是ios編程的一種設計模式。我們可以用這個設計模式來讓單繼承的objective-c類表現出它父類之外類的特徵。昨天這個代理實現如下:
類GifView是繼承自UIView的,它載入在RootViewController上來通過一個Timer播放動畫。同時,RootViewController需要知道Timer的每次執行。
代碼如下。
首先,定義GifView,在其標頭檔中定義代理EveryFrameDelegate,同時聲明方法- (void)DoSomethingEveryFrame;
#import <UIKit/UIKit.h>@protocol EveryFrameDelegate <NSObject>- (void)DoSomethingEveryFrame;@end@interface GifView : UIView { NSTimer *timer; id <EveryFrameDelegate> delegate; NSInteger currentIndex;}@property (nonatomic, retain) id <EveryFrameDelegate> delegate;@end
然後,只要在GifView.m中讓Timer在每次執行的時候調用delegate來執行DoSomethingEveryFrame,代碼如下
- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(play) userInfo:nil repeats:YES]; [timer fire]; } return self;}-(void)play{ [delegate DoSomethingEveryFrame]; }
GifView上的工作就完成了。
下面是RootViewController中的代碼,RootViewController只要在定義GifView的時候指定其代理為自身,就可以知道Timer的每次執行:
- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CGRect rect = CGRectMake(0, 0, 200, 200); GifView *tmp = [[GifView alloc] initWithFrame:rect]; tmp.delegate = self; [self.view addSubview:tmp]; [tmp release];}- (void)DoSomethingEveryFrame{ NSLog(@"I'm the delegate! I'm doing printing!");}
GifView中Timer每次執行都會列印一行
I'm the delegate! I'm doing printing!
故,RootViewController就知道Timer的每次執行了。
做程式時,經常會碰到這樣一種情況:在對象A中有一個對象B,在B中做某個操作時需要調用A對象的某個方法。這時,我們就需要用代理機制,也叫委託機制。
還記得剛接觸物件導向的時候,居然在B對象中又alloc了一個A對象,發現執行方法時沒有works,那時不理解新alloc的對象和原來的對象A不是一個東東。
今天專門補習了一下哈,在網上找了一些資料,綜合了一下,寫了這篇菜鳥教程。
委託代理(delegate),顧名思義,把某個對象要做的事情委託給別的對象去做。那麼別的對象就是這個對象的代理,代替它來打理要做的事。反映到程式中, 首先要明確一個對象的委託方是哪個對象,委託所做的內容是什麼。委託機制在很多語言中都用到的,這隻是個通用的思想,網上會有很多關於這方面的介紹。
下面以一個簡單的例子介紹一下委託:
一、建立iPhone項目DelegateDemo;
二、添加UIView類ViewA;
三、ViewA.h的內容如下:
#import <UIKit/UIKit.h>@protocol ViewADelegate; //申明代理協議@interface ViewA : UIView {id <ViewADelegate> _viewADelegate;}@property (nonatomic, assign) id viewADelegate; //定義代理的屬性,同時要在.m加中@end//代理協議的內容@protocol ViewADelegate <NSObject>- (void)viewACallBack;@endView.m中: @synthesize viewADelegate = _viewADelegate;
三、在DelegateDemoViewController.m中:
- (void)viewDidLoad {ViewA *viewA = [[ViewA alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];viewA.viewADelegate = self; //設定viewA的代理為當前對象自己[self.view addSubview:viewA];[viewA release];[super viewDidLoad];}- (void)viewACallBack {NSLog(@"Hi, I am back!");}
四、
點擊此處下載樣本。