delegate使用新想法

平时工作肯定会遇到delegate的使用,比较常用的UITableViewDelegateUITableViewDataSource, 有关delegate的特点以及使用可以参考苹果官方文档

delegate & struct

最近在阅读SRSocketRocket源代码时候发现了一个之前没接触过的方式,代码中为protocol包装了一层,使用struct构建一个对象来标识实现这个协议的对象都实现了哪些方法:

delegateWrapper
delegateWrapper

我为此写了一个Demo,简单的介绍了这种新的方式。

Demo

Demo比较简单,三个页面用来区分平时使用方法和这次新的使用方法。

首先定义了一个协议HBDemoProtocol,包含两个接口给要实现者去实现。

1
2
- (void)sayHello;
- (void)sayBye;

ViewController是APP启动看见的页面,
一般实现按钮将页面带入平时使用方式调用页面;
包装实现按钮将页面带入这次新方法调用页面。

Origin

定义HBOriginModel对象用来调用HBDemoProtocol的实现。
HBOriginViewController VC是平时使用方式,实现HBDemoProtocol。主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (IBAction)sayHelloAction:(id)sender {
[self.originModel sayHelloAction];
}
- (IBAction)sayByeAction:(id)sender {
[self. originModel sayByeAction];
}
- (void)alertTitle:(NSString *)title {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)sayHello {
[self alertTitle:@"sayHello"];
}
- (void)sayBye {
[self alertTitle:@"sayBye"];
}

点击sayHellosayBye按钮弹出不同的文言。

新的思路

对协议HBDemoProtocol做一个封装对象HBProtocolWrapper,定义结构体标识协议对应的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct HBDemoProtocolAvalibale {
BOOL sayHello : 1;
BOOL sayBye : 1;
};
typedef struct HBDemoProtocolAvalibale HBDemoProtocolAvalibale;
typedef void(^HBDemoProtocolBlock)(id<HBDemoProtocol> delegate, HBDemoProtocolAvalibale delegateAvalible);
....
- (void)setDelegate:(id<HBDemoProtocol>)delegate {
dispatch_barrier_async(self.accessQueue, ^{
_delegate = delegate;
self.delegateAvalible = (HBDemoProtocolAvalibale){
.sayHello = [delegate respondsToSelector:@selector(sayHello)],
.sayBye = [delegate respondsToSelector:@selector(sayBye)],
};
});
}

这样在调用协议实现时可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)setDelegate:(id<HBDemoProtocol>)delegate {
self.protocolWrapper.delegate = delegate;
}
- (void)sayHelloAction {
[self.protocolWrapper performDelegateBlock:^(id<HBDemoProtocol> delegate, HBDemoProtocolAvalibale delegateAvalible) {
if (delegateAvalible.sayHello) {
[delegate sayHello];
}
}];
}
- (void)sayByeAction {
[self.protocolWrapper performDelegateBlock:^(id<HBDemoProtocol> delegate, HBDemoProtocolAvalibale delegateAvalible) {
if (delegateAvalible.sayBye) {
[delegate sayBye];
}
}];
}

HBWrapperViewController 页面与 HBOriginViewController实现上基本一致。
将对delegate操作的代码和附加功能(delegate操作的队列等)做拆分,这样拆分了代码,阅读以及测试起来更加方便。

这是一些阅读源代码的发现,如果你有其它意见或者见解欢迎留言(注意:留言系统是Disqus)或者发我邮箱:honeyeeeb@gmail.com。谢谢!

需要多读一读优秀源代码,O(∩_∩)O~~

以上:如果有错误或者任何问题欢迎指正(评论系统集成的Disqus,所以你可能看不见🙈🤷‍♂️)!!!

如果你还没有顺手的科学上网工具,推荐一个我正在用的SSR服务, 多条线路可供选择使用,一年不限流量 ¥200 。现在购买的时候输入优惠码 qj80 还享受 八折 优惠!