程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Objective-c中的delegate淺析

Objective-c中的delegate淺析

編輯:關於C語言

delegate初探

在ios開發中,我們經常會用到類似如下的對話框:

\

因此,如下這段代碼我們也就很熟悉了:

- (IBAction)showSheet:(id)sender {
    UIActionSheet *actionSheet = [[UIActionSheet alloc]
                                  initWithTitle:@"title,nil時不顯示"
                                  delegate:self
                                  cancelButtonTitle:@"取消"
                                  destructiveButtonTitle:@"確定"
                                  otherButtonTitles:@"第一項", @"第二項",nil];
    actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
    [actionSheet showInView:self.view];
}
其中initWithTitle函數的第二個參數為delegate,那麼是什麼呢? 我們到它的頭文件中看看。initWithTitle這個函數的聲明如下 :

- (id)initWithTitle:(NSString *)title delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
是的,上面這個巨長無比的函數聲明就是initWithTitile函數,oc這個語言本身給我的感覺就是繁雜。廢話不多說,我們直接看到delegate參數的類型是id,直接看UIActionSheetDelegate的聲明:

@protocol UIActionSheetDelegate 
@optional

// Called when a button is clicked. The view will be automatically dismissed after this call returns
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;

// Called when we cancel a view (eg. the user clicks the Home button). This is not called when the user clicks the cancel button.
// If not defined in the delegate, we simulate a click in the cancel button
- (void)actionSheetCancel:(UIActionSheet *)actionSheet;

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet;  // before animation and showing view
- (void)didPresentActionSheet:(UIActionSheet *)actionSheet;  // after animation

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex; // before animation and hiding view
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex;  // after animation

@end
可以看到UIActionSheetDelegate是一個普普通通的協議,在@optional下面有六個函數,這些函數都是可選實現的,每個函數對應的是UIActionSheet中每個按鈕的點擊事件處理,當然最後兩個函數是按照索引來區分Button對象的。

delagate的實現

協議與delegate不是同一概念,協議是語言級別的特性,而delegate是借助協議來的實現的一種設計模式,其實就是代理模式。通過注入代理對象實現相應的功能。其實它的主要功能也就是實現回調,與Java中的listener一樣。

下面以一個示例來說明 :

// ButtonClickDelegate協議
@protocol ButtonClickDelegate 

-(void) onClick: (id) sender ;

@end


// view的聲明,實現了ButtonClickDelegate協議
@interface UIView : NSObject    
{
@protected id clickDelegate ;
}

// 點擊事件代理,因此UIView實現了ButtonClickDelegate協議,因此自己可以為自己代理。
@property (nonatomic, strong) id clickDelegate ;
// 點擊view的觸發函數
-(void) performClick ;

@end

// view的實現
@implementation UIView

@synthesize clickDelegate ;

// 默認的點擊事件
-(id) init
{
    self = [super init] ;
    if ( self ) {
        clickDelegate = self ;
    }
    return self;
}

// 點擊view的事件的默認處理
-(void) onClick: (id) sender
{
    NSLog(@"點擊view的默認處理函數.") ;
}

// 點擊事件
-(void) performClick
{
    [clickDelegate onClick: self ] ;
}

@end



// ViewController聲明, 實現了ButtonClickDelegate協議,可以作為UIView的代理
@interface ViewController : NSObject 
@property (nonatomic, strong) UIView* parenView ;
@end

// ViewController實現
@implementation ViewController

-(void) onClick:(id)sender
{
    NSLog(@"ViewController來實現點擊事件") ;
}

@end
main函數:

// main
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // view對象
        UIView* view = [[UIView alloc] init] ;
        [view performClick] ;
        
        // 構建一個ViewController對象
        ViewController* controller = [[ViewController alloc] init] ;
        view.clickDelegate = controller ;
        [view performClick] ;
        
    }
    return 0;
}

首先創建了一個UIView對象view, 然後調用performClick函數,此時view沒有設置delegate,但是由於自己實現了ButtonClickDelegate協議,因此可以為自己代理該點擊事件。然後我們創建了ViewController對象controller, 並且將該對象設置為view對象的delegate, 然後執行performClick函數,此時在performClick函數中

會執行ViewController中的onClick函數,即controller代理了view的點擊事件處理。輸出結果如下 :

點擊view的默認處理函數.
ViewController來實現點擊事件

delegate與Java中的Listener

delegate與Java中的Listener的功能大致是相同的,比如我們看看Android中一個按鈕的點擊事件的處理。

	Button	mJumpButton = (Button) findViewById(R.id.button_jump);
	mJumpButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(MainActivity.this,
						SecondActivity.class);
				startActivity(intent);
			}
		});

其中的Button就相當於上文中的UIView,而其setOnClickListener就相當於delegate屬性的設置方法,OnClickListener就扮演了上文中ButtonClickDelegate的角色,

onClick方法更是如出一轍。其實每個平台大體上的設計思路也都是很相近的,觀察不同平台的對比實現更容易理解吧。


delegate與id類型

我們在聲明一個delegate對象是的形式是如下這樣的 :

// 點擊事件代理,因此UIView實現了ButtonClickDelegate協議,因此自己可以為自己代理。
@property (nonatomic, strong) id clickDelegate ;

注意這裡的類型是id;這表明該delegate對象可以是任意類型,但是該類型必須實現ButtonClickDelegate協議,也可以說成該類型必須采用正式協議ButtonClickDelegate。這個就很像Java中的泛型,例如我們可以在Java中這樣使用泛型,

void setData(List myorders) ;
在setData函數中接受的參數為元素類型為Order子類的List集合,與id是不是又很相似呢?

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved