免费开源的iOS开发学习平台

OC基础:代理协议(Delegate)

在iOS开发中,经常使用到代理(委托)协议以及数据源协议,所谓代理(委托)协议,通俗来讲,顾名思义就是委托别人办事,就是当一件事情发生后,自己不处理,让别人来处理。例如,用户点击了一个子控件上的按钮,这时可以委托控制器去做一些事情,例如切换到另外的控制器或者发送一个网络请求等。代理协议也是协议,因此实现自定义代理协议的方法与协议的实现,基本一致。

代理协议的实现

下方的示例代码中实现了在一个UIView的视图类中实现代理协议,并添加一个代理协议方法,当用户发生点击操作时会执行遵守代理协议对象中实现的协议方法。

  • 在自定义视图类MYView.h文件中:设置类引用@class、定义代理协议名称、定义代理协议中包含的方法、添加代理属性(注意使用weak属性); (注意:协议中的方法,一般情况下(不强制),通常第一个参数都是对象自身,这样做的好处在于:在遵守协议的类中,实现协议中的方法时,可以获取到一些有用信息。)
#import <UIKit/UIKit.h>
@class MYView;
@protocol MyViewDelegate <NSObject>
-(void) myView:(MYView *) myView clickMYButtonShowAlert:(NSString *) message;
@end 
@interface MYView : UIView
@property (nonatomic, weak) id <MyViewDelegate> delegate; 
@end
  • 在MYView.m文件中,监听代理协议定义事件的发生,当事件发生时,通知遵守代理协议的对象(如控制器)去工作,即设置在实现代理协议的类中,代理协议方法执行的时机;(注意:我们在通知遵守代理协议的对象(self.delegate)在调用协议方法之前,通常会先判断一下该对象中,是否已经实现了该协议方法,即是否响应代理协议方法对应的消息,使用respondsToSelector:方法。)
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    if ([self.delegate respondsToSelector:@selector(myView:clickMYButtonShowAlert:)]) {
        [self.delegate myView:self clickMYButtonShowAlert:@"视图被点击了"];
    }
}
  • 在需要遵守代理协议的类中,引用头文件并遵守代理协议,遵守代理协议需要在类的接口部分使用<>符号来声明该类需要遵守的协议,同一个类可以遵守多个协议
#import "MYView.h"
@interface ViewController () <MyViewDelegate>
@property (nonatomic,strong) MYView *myView;
@end
  • 设置代理对象。
-(MYView *)myView{
    if (_myView == nil) {
        _myView = [[MYView alloc] init];
        _myView.frame = CGRectMake(0, 500, 320, 50);
        _myView.backgroundColor = [UIColor yellowColor];
        _myView.delegate = self;//设置代理对象
    }
    return _myView;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.myView];
}
  • 实现协议方法。即当触发条件发生时,执行的动作。
-(void)myView:(MYView *)myView clickMYButtonShowAlert:(NSString *)message{
    NSLog(@"%s",__func__);
    NSLog(@"传递的消息是:%@",message);
}

运行结果如下。当我们点击屏幕上面红色的视图对象时,会打印如下的日志,通过日志我们可以看到,当点击视图对象时,调用的是控制器类中实现的代理协议,同时,视图对象可以传递信息(message)给控制器对象,从而实现了对象之间的通信。

示例代码

https://github.com/99ios/5.3.2