OC是没有多继承的,所以在很多时候,需要使用到协议(protocol)。前面有文章对协议进行了简单的介绍,这里就不多说了。这里说一下一个与协议有关的东西----委托代理(delegate)。
委托代理是指给一个对象提供一个机会,对另一个对象中的变化做出反应,或者响应另一个对象的行为。它的基本思想是两个对象协同解决问题。
委托代理,其实是两个部分,委托和代理,在程序中委托和代理协同处理问题。
1、委托的工作内容:
定义协议与方法;
声明委托变量;
设置代理;
通过委托变量调用委托方法;
2、代理的工作内容:
遵守协议;
实现委托方法;
在实际的开发中,委托代理这个设计模式主要用来实现页面之间的传值,而且是反向传值,何为反向?当A页面跳转到B页面称为正向,B页面返回到A页面为反向。代理就可以用来处理当在B页面处理数据后想要在页面返回时给A页面传值的问题。下面,直接上代码,在代码中在详细讲解如何一步一步的时间委托代理从而实现传值。
代码:
ViewController.m代码:
#import "ViewController.h"
#import "SecondViewController.h"
//6、遵守协议
@interface ViewController ()<SecondViewControllerDelegate>
{
UILabel *label;
UIButton *button;
SecondViewController *secondVC;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//7、初始化对象
secondVC = [[SecondViewControlleralloc]init];
//8、设置代理
secondVC.delegate =self;
[selfsetUI];
}
//9、实现协议方法
- (void)sendValue:(NSString *)string{
label.text = string;
}
- (void)setUI{
label = [[UILabelalloc]initWithFrame:CGRectMake(100, 200, 200, 30)];
label.backgroundColor = [UIColoryellowColor];
label.text =@"没有接收到传值";
[self.viewaddSubview:label];
button = [UIButtonbuttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(100, 300, 200, 30);
[buttonsetTitle:@"页面跳转"forState:UIControlStateNormal];
[buttonsetBackgroundColor:[UIColorblueColor]];
[buttonaddTarget:selfaction:@selector(post)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:button];
}
- (void)post{
secondVC.title =@"第二个页面";
[self.navigationControllerpushViewController:secondVCanimated:YES];
}
@end
SecondViewController.h代码:
#import <UIKit/UIKit.h>
//1、声明协议
@protocol SecondViewControllerDelegate <NSObject>
//2、声明协议方法
- (void)sendValue:(NSString *)string;
@end
@interface SecondViewController :UIViewController
//3、声明代理
@property (nonatomic,weak) id delegate;
@end
SecondViewController.m代码:#import "SecondViewController.h"
@interface SecondViewController ()
{
UIButton *button;
UITextView *textField;
}
@end
@implementation SecondViewController
- (void)viewDidLoad {
[superviewDidLoad];
self.view.backgroundColor = [UIColorwhiteColor];
//创建一个textField输入的内容就是要传递的值
textField = [[UITextViewalloc]initWithFrame:CGRectMake(100, 200, 200, 30)];
textField.layer.borderWidth = 0.5;
textField.textColor = [UIColorblackColor];
[self.viewaddSubview:textField];
button = [UIButtonbuttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(100, 300, 200, 30);
[buttonsetTitle:@"返回上一个页面"forState:UIControlStateNormal];
[buttonsetBackgroundColor:[UIColorblueColor]];
[buttonaddTarget:selfaction:@selector(pop)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:button];
}
- (void)pop{
//4、判断协议是否响应如果协议响应了sendValue:方法
if ([_delegaterespondsToSelector:@selector(sendValue:)]) {
//5、通知执行协议方法将textField中输入的值传递给上一个页面
[_delegatesendValue:textField.text];
}
//页面返回
[self.navigationControllerpopViewControllerAnimated:YES];
}
@end
代码运行结果:代码开始运行: 跳转到下一个页面,输入要传递的值: 页面返回,显示结果:
现在,回头来看看代码,回忆一下,委托代理的实现步骤:
//1、声明协议 这里的协议名称尽可能明了和有标识。
@protocol SecondViewControllerDelegate <NSObject>
//2、声明协议方法 协议方法名称也尽可能要体现功能
- (void)sendValue:(NSString *)string;
//3、声明代理 代理是一个id类型的 这里的修饰符必须使用weak否则会有内存泄漏,关于内存泄漏的问题以后会说
@property (nonatomic, weak) id delegate;
第四步和第五步是在一起的一个操作。并且在后面就是页面返回操作
- (void)pop{
//4、判断协议是否响应 如果协议响应了sendValue:方法
if ([_delegate respondsToSelector:@selector(sendValue:)]) {
//5、通知执行协议方法 将textField中输入的值传递给上一个页面
[_delegate sendValue:textField.text];
}
//页面返回
[self.navigationController popViewControllerAnimated:YES];
}
//6、遵守协议
@interface ViewController ()<SecondViewControllerDelegate>
//7、初始化对象
secondVC = [[SecondViewController alloc]init];
//8、设置代理
secondVC.delegate = self;
//9、实现协议方法
- (void)sendValue:(NSString *)string{
label.text = string;
}
从上面的步骤可以看到,委托代理的使用,是从传值页面开始的。现在,来一个通俗的解释:
A(ViewController)页面是上一级页面,可以跳转到B(SecondViewController)页面,而传值方向是从B传递到A。代码中是B设置了委托,A实现了代理并实现委托方法。可以简单理解为,B想要将值传递给A,但是没有好的方法(不能直接传值),这个时候,B就想委托A自己取值,这个时候,B就设计了一套委托协议,A想要得到B的值,但是B不能直接传递给A,A就问啦:B啊,你怎么不给我传值啊,我很急啊。然后B就对A说,我这里没有通道,不能直接给你啊,我这有一套委托协议,你来遵守我的协议然后自己来取值吧。这样A就作为了B的代理方,通过实现代理方法得到了想要的值。
在使用委托代理传值的是,要传值的一方是委托方,要接收的一方是代理方。在委托方要声明协议,声明代理,声明协议方法;而在代理方要遵守协议,设置代理,实现协议方法。这样相互之间一一对应的关系就使得委托代理在定向传值的时候显得特别的重要和实用。
好了,委托代理的使用到这里就差不多说完了。刚开始接触的人会觉得代理是个什么东西啊?又是协议,又是代理,又是委托的,乱死了。可是仔细的自己写一个出来以后就会发现其实很简单,每一步之间都是有关联的,委托和代理之间也是有对应的。所以,它并不难,别把它给妖魔化了。