Objective-c中的delegate淺析

delegate初探

在ios開發中,咱們經常會用到相似例如如下的對話框:java


所以,例如如下這段代碼咱們也就很是熟悉了: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<UIActionSheetDelegate>)delegate cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
是的,上面這個巨長無比的函數聲明就是initWithTitile函數,oc這個語言自己給個人感受就是繁雜。廢話很少說,咱們直接看到delegate參數的類型是id<UIActionSheetDelegate>。直接看UIActionSheetDelegate的聲明:

@protocol UIActionSheetDelegate <NSObject>
@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的點擊事件處理。固然最後兩個函數是依照索引來區分Button對象的。

delagate的實現

協議與delegate不是同一律念,協議是語言級別的特性,而delegate是藉助協議來的實現的一種設計模式,事實上就是代理模式。經過注入ide

代理對象實現對應的功能。函數

事實上它的主要功能也就是實現回調,Java中的listener同樣。post

如下以一個演示樣例來講明 :this

// ButtonClickDelegate協議
@protocol ButtonClickDelegate <NSObject>

-(void) onClick: (id) sender ;

@end


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

// 點擊事件代理。所以UIView實現了ButtonClickDelegate協議,所以本身可以爲本身代理。
@property (nonatomic, strong) id<ButtonClickDelegate> 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 <ButtonClickDelegate>
@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函數中atom

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

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

delegate與Java中的Listener

delegate與Java中的Listener的功能大體是一樣的,比方咱們看看Android中一個button的點擊事件的處理。設計

	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方法更是一模一樣。事實上每個平臺大致上的設計思路也都是很是相近的,觀察不一樣平臺的對照實現更easy理解吧。


delegate與id類型

咱們在聲明一個delegate對象是的形式是例如如下這種 : 

// 點擊事件代理,所以UIView實現了ButtonClickDelegate協議。所以本身可以爲本身代理。
@property (nonatomic, strong) id<ButtonClickDelegate> clickDelegate ;

注意這裏的類型是id<ButtonClickDelegate>;這代表該delegate對象可以是隨意類型,但是該類型必須實現ButtonClickDelegate協議也可以說成該類型必須採用正式協議ButtonClickDelegate。這個就很是像Java中的泛型。好比咱們可以在Java中這樣使用泛型,

void setData(List<? extends Order> myorders) ;
在setData函數中接受的參數爲元素類型爲Order子類的List集合,與id<ButtonClickDelegate>是否是又很是類似呢?
相關文章
相關標籤/搜索