惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
The Register - Security
The Register - Security
D
Docker
The Cloudflare Blog
A
About on SuperTechFans
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
月光博客
月光博客
B
Blog RSS Feed
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
B
Blog
IT之家
IT之家
美团技术团队
Engineering at Meta
Engineering at Meta
C
Check Point Blog
云风的 BLOG
云风的 BLOG
Last Week in AI
Last Week in AI
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
H
Help Net Security
雷峰网
雷峰网
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
PCI Perspectives
PCI Perspectives
J
Java Code Geeks
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
腾讯CDC
A
Arctic Wolf
C
CERT Recently Published Vulnerability Notes
量子位
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Hacker News
The Hacker News
有赞技术团队
有赞技术团队
Schneier on Security
Schneier on Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

壹拾肆

2024 年做过的一些梦 2023 年做过的一些梦 2023 年终总结丨随时开始奔跑的心气 2022 年终总结丨惠存这一年 翻译:Why use dependency injection 是时候维护一个属于自己的开源库了 iOS 端豆瓣开源许可提到的库 推荐几个播客节目 iOS 自动化打包上传 AppleStore、fir.im,并发邮件通知测试人员 业余剪辑自我修养 Swift - 权限请求封装 iOS - HMAC 加密算法和一个 MD5 加密的问题 iOS - 一些蓝牙问题的解决 Swift - 顶部弹出框封装 被光放弃的人 我的 AIO-notion 工作流搭建 解决使用 GitPage 重定向多次问题 Swift - ?和!的学习 《文学回忆录》读书笔记
OC - 多代理的实现
Kaaaaai · 2020-07-16 · via 壹拾肆

一、背景

迭代项目的时候碰到一个问题, 原因是负责的内容有一项是封装各大 AI 开放平台的 SDK 集成到一个 SDK 里,然后输出统一的接口,目的是为了可以在不同的 AI 中快速切换并使用。但由于之前输出给了兄弟公司使用,他们在一个音乐 SDK 中用语音 SDK 实现语音点歌的功能。然后当我的主应用同时使用两个 SDK 时,由于音乐 SDK 中实现了语音 SDK 的代理,所以我在上层再初始化语音 SDK 设置代理就不起作用。

二、解决方式

知道问题原因后,就比较容易解决了,具体有几种思路:

  1. 打电话给兄弟公司的开发人员,你不要这样弄了,如果你非要这么弄,就暴露一个接口给我,让我选择是否要让你初始化。
  2. 延迟上层语音 SDK 的初始化,不和你抢代理的设置,就不存在被抢夺这件事了。
  3. 语音 SDK 实现多代理——既然你们都要实现我的代理方法,我就全部都给你们。

作为一个有追求的开发仔,当然选择实现最高难度的自己实现多代理的方式——虽然由于时间关系,也用了第二种方式作为缓冲,然后也发现第二种方式存在一个问题,就是当网络较差的情况下,未能初始化成功,在初始化成功后,音乐 SDK 又会设置一次语音 SDK 的代理,又被抢回去了~

三、具体实现

实现的过程中,以下几篇文章的内容给了我很大的帮助:

两篇文章都讲的很细,所以对于有些细节就不展开讲了,只讲一下具体实现原理:

  1. 首先理解代理模式。也就是由一个对象 A 通过他的唯一一个代理成员把消息发个对象 B。
  2. 多代理就是在第一步的基础上,把对象 A 的代理成员从唯一一个,拓展为多个,消息接收者也从单一的 B,可以延伸为 B1、B2、B3…Bx。

所以实现的时候很简单。

1.定义一个储存多个代理成员的数组:

1
2
3
4
5
6
7
8
@property (strong, nonatomic) NSPointerArray* delegates;

-(NSPointerArray *)delegates{
if (!_delegates) {
_delegates = [[NSPointerArray alloc]init];
}
return _delegates;
}

2.重写代理的 set 方法

1
2
3
4
5
6
7
8
9
- (void)setDelegate:(id<ManagerDelegate>)delegate{

for (id existDelegate in self.delegates) {
if ([delegate isEqual:existDelegate]) {
return;
}
}
[_delegates addPointer:(__bridge void*)delegate];
}

3.多代理响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)asrResultIsTimeOut{
if (self.currentCount != 0) {
self.currentCount--;
}else{
[self.asrTimer invalidate];
self.asrTimer = nil;
for (id delegate in self.delegates) {
if ([delegate respondsToSelector:@selector(asrManagerActiveError:)]) {
[delegate asrManagerActiveError:NETWORKERROR];
}
}

//原始响应方法
// if ([self.asrDelegate respondsToSelector:@selector(asrManagerActiveError:)]) {
// [self.asrDelegate asrManagerActiveError:TIMEOUT];
// }
}
}

四、拓展阅读

在实现的过程中,我一开始用的是 NSMutableArray,因为使用运行也没有什么问题,但看到👆多代理文章里说,用 NSPointerArray 会好点,不增加成员的应用计数,相当于弱引用。听起来不错哦,但忽然之前想到一个问题,为什么 delegate 一一定要用 weak 引用呢,这个问题之前一直没仔细去思考过,像灯下黑,一直用的反倒忽略了。当下,想起来就去百度了一下。在这里看到:iOS 代理为啥要用weak修饰? (刨根问底一)——刨根问底的副标题深得我心~,里面有生动详细的例子说明,简单来说就是强引用会出现循环引用的问题。