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>是否是又很是类似呢?
相关文章
相关标签/搜索