天天看點

iOS監聽模式系列之關于delegate(代理,委托)的學習

首先,大家應該都明白的是委托是協定的一種,顧名思義,就是委托他人幫自己去做什麼事。也就是當自己做什麼事情不友善的時候,就可以建立一個委托,這樣就可以委托他人幫自己去實作什麼方法。

其次,我簡單的總結了一下自己用到的委托的作用有兩個,一個是傳值,一個是傳事件。 1.所謂傳值經常用在b類要把自己的一個資料或者對象傳給a類,讓a類去展示或者處理。(切分緊耦合,和代碼分塊的時候經常用) 2.所謂傳事件就是a類發生了什麼事,把這件事告訴關注自己的人,也就是委托的對象,由委托的對象去考慮發生這個事件後應該做出什麼反映。(這個經常見,例如在異步請求中,界面事件觸發資料層改變等等) 3.利用委托指派,這種方法感覺是為了不暴露自己的屬性就可以給自己複值,而且這樣更友善了類的管理,隻有在你想要讓别人給你指派的時候才調用,這樣的指派更可控一些。(例如tableView中的委托(dateSource)中常見)。

最後,我想分享一下在使用委托的時候的一些心得和注意事項。

心得:delegate的命名要準确,盡量看名字就知道用法。delegate和通知有的用法有些象,但是前者是單對單的,後者是單對多的情況。 注意:在dealloc要把delegate至為nil,還有就是delegate設定屬性的時候要用assign,不要用retain。   委托

在IOS中委托通過一種@protocol的方式實作,是以又稱為協定.協定是多個類共享的一個方法清單,在協定中所列出的方法沒有響應的實作,由其它人來實作.這叫好比我想買個手機,是以我有個buyIphone 方法,但是我不知道誰那買手機,是以把這個需求釋出出去(比如公布在網站上),如果有賣手機的商人(也就是說他能實作buyIphone這個方法)看到,他就會接受我的委托,(在商人自己的類中實作<XXXdelegate>),那麼我的委托對象就指向了這個商人..當我要買手機的時候,直接找他就行了.

例如:

iOS監聽模式系列之關于delegate(代理,委托)的學習
@protocol MyDelegate
-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money;

@end
@interface My : NSObject
{
    id<MyDelegate> deleage;
}
@property(assign,nonatomic)id<MyDelegate> delegate;
@end      
iOS監聽模式系列之關于delegate(代理,委托)的學習

代碼中聲明了一個協定 名叫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方法

iOS監聽模式系列之關于delegate(代理,委托)的學習
#import "Business.h"

@implementation Business

-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money
{
    NSLog(@"手機有貨,這個價錢賣你了,發貨中!!");
}
@end      
iOS監聽模式系列之關于delegate(代理,委托)的學習

委托是Cocoa中最簡單、最靈活的模式之一。委托是指給一個對象提供機會對另一個對象中的變化做出反應或者影響另一個對象的行為。其基本思想是:兩個對象協同解決問題。一個對象非常普通,并且打算在廣泛的情形中重用。它存儲指向另一個對象(即它的委托)的引用,并在關鍵時刻給委托發消息。消息可能隻是通知委托發生了某件事情,給委托提供機會執行額外的處理,或者消息可能要求委托提供一些關鍵的資訊以控制所發生的事情。

iOS監聽模式系列之關于delegate(代理,委托)的學習

 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;

iOS監聽模式系列之關于delegate(代理,委托)的學習
#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      
iOS監聽模式系列之關于delegate(代理,委托)的學習

然後,隻要在GifView.m中讓Timer在每次執行的時候調用delegate來執行DoSomethingEveryFrame,代碼如下

iOS監聽模式系列之關于delegate(代理,委托)的學習
- (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];
 
}      
iOS監聽模式系列之關于delegate(代理,委托)的學習

GifView上的工作就完成了。

下面是RootViewController中的代碼,RootViewController隻要在定義GifView的時候指定其代理為自身,就可以知道Timer的每次執行:

iOS監聽模式系列之關于delegate(代理,委托)的學習
- (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!");
}      
iOS監聽模式系列之關于delegate(代理,委托)的學習

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的内容如下:

[cpp]  view plain  copy

  1. #import <UIKit/UIKit.h>  
  2. @protocol <a href="http://www.wuleilei.com/" target="_blank"><span style="color:#ff0000">ViewADelegate</span></a>; //申明代理協定  
  3. @interface ViewA : UIView {  
  4.     id <<a href="http://www.wuleilei.com/" target="_blank"><span style="color:#ff0000">ViewADelegate</span></a>> _viewADelegate;  
  5. }  
  6. @property (nonatomic, assign) id viewADelegate; //定義代理的屬性,同時要在.m加中  
  7. @end  
  8. //代理協定的内容  
  9. @protocol <a href="http://www.wuleilei.com/" target="_blank"><span style="color:#ff0000">ViewADelegate</span></a> <NSObject>  
  10. - (void)<span style="color:#008080">viewACallBack</span>;  
  11. @end  
  12. View.m中:  
  13. <span> </span>@synthesize viewADelegate = _viewADelegate;  

三、在DelegateDemoViewController.m中:

- (void)viewDidLoad {
	ViewA *viewA = [[ViewA alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
	viewA.viewADelegate = self; //<a target=_blank href="http://www.wuleilei.com/" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" style="color: rgb(51, 102, 153); text-decoration: none;"><span style="color: rgb(255, 0, 0);">設定viewA的代理為目前對象自己</span></a>
	[self.view addSubview:viewA];
	[viewA release];
	[super viewDidLoad];
}

- (void)<span style="color: rgb(0, 128, 128);">viewACallBack</span> {
	NSLog(@"Hi, I am back!");
}      

四、

點選此處下載下傳示例。