记录一下关于项目中“事件回调”的一些想法
协议(代理)方法 和 事件方法(可能也是伪代理方法)
在项目中层与层之间、类与类之间有着参数的相互传递。尤其是对于项目逻辑比较复杂,层级关系不较多的程序而言。一个好的事件回调方法尤为重要。
首先前提以一个层级关系为示例:(A-->B-->C-->D-->...)
1.关于代理方法:代理方法一般是使用在具有父子层级关系(父控件和子控件)的两个类中。那如果是两个爷孙层级或者是辈分隔得更远的层级关系的类中该怎么相互传递参数呢?
1.1>可能有人说用通知。是的通知是可以使更远层的两个类相互联系起来,但是一个项目中有这么多远关系的层级交错,总不能遍地是通知吧,这显然是行不通的。
1.2>那么我们可以确定一个思路:那就是一级一级的回调。D-->C-->B-->A.
可以定义两个基础类:一个baseView(继承UIView);一个baseViewController(继承UIViewController)。两个基础类都定义一个delegate属性和协议(代理)方法。这样,所有继承于这两个基础类的类都能够具有了这个协议。那这样就可以使用[self.delegate 协议方法];进行层层回调。
2.事件回调方法(伪代理):给每一个创建的类都添加一个”parent“属性和”回调方法“。但没有引入协议(所以是伪代理)。然后仍然是利用[self.parent 回调方法];来回调的上层。
3.代理方法 和 事件回调方法的区别与注意点:
3.1>代理方法(即协议)在编译的时候已经确定了self.delegate的真正的类型;或者是代理方法中的self.delegate在编译的时候也不知道其真正类型,但是代理方法中不用考虑self.delegate是否有这个代理方法。执行[self.delegate 协议方法]的时候不会提示警告或错误。(非官方解释)
3.2>事件回调只是在运行时确定self.parent的真正的类型,在编译的时候不能确定真正类型。故在调用[self.parent 回调方法]时,有时候会报错:找不到回调方法。
3.2>注意点:对于事件回调,由于不知道self.parent的真正类型,对于self.parent调用的方法,编译时系统会默认去当前类中去找、不会去真正的类型中去找。因此,为了避免报错,当前类中也要有这个回调方法。
举个实例:
代理略过。
伪代理:
1.父控件控制器.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
- (void)setHUIDIAO:(void *)action;//伪代理的回调方法
@end
2.父控件控制器.m
#import "ViewController.h"
#import "OneView.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
OneView *one = [[OneView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
one.parent = self;//类似于代理
[one getLog];//视图调用此方法来响应父控件的回调
[self.view addSubview:one];
}
//伪代理的回调方法实现
- (void)setHUIDIAO:(void *)action
{
NSLog(@"%@",action);
}
@end
3.子控件view.h
#import <UIKit/UIKit.h>
@interface OneView : UIView
@property (nonatomic,strong)id parent;//类似于代理的属性
- (void)setHUIDIAO:(void *)action;//此类的回调方法
- (void)getLog;
@end
4.子控件view.m
#import "OneView.h"
@implementation OneView
- (void)getLog
{
[self.parent setHUIDIAO:@"hello"];//父类的回调方法
}
- (void)setHUIDIAO:(void *)action
{
}
@end
5.本来self.parent == viewController,OneView.h中没必要写”- (void)setHUIDIAO:(void *)action;//此类的回调方法“方法的。现在把此方法为注释掉后,结果如图:
报错:找不到”setHUIDIAO:“方法.
6.由此可见,伪代理方法,在不知道self.parent真正类型的情况下,是默认self本身有没有这个方法。