iOS 一对多 delegate 的简单应用

栏目: IOS · 发布时间: 5年前

内容简介:在之前我们尝试过 hook webView 的 delegate,可以查看【现在我们可以通过更简单的方式来实现,在 hook webView 的初始化方法后,使用一对多委托方式,将 webView 的 delegate 设置为我们内部实现相关协议的对象,使得我们的 hook 代码不影响原始代码的 delegate 实现。为什么突然想到可以这样来实现功能?其实启发是来源于优秀的开源框架

在之前我们尝试过 hook webView 的 delegate,可以查看【 iOS 如何优雅地 hook 系统的 delegate 方法 】。当时的思路是,由于 delegate 只能是一对一的消息传递,后面设置的 delegate 对象会替换前面设置的 delegate 对象,因此在无入侵的情况下,需要通过 setDelegate 方法找到设置的 delegate 对象,然后 hook 该对象实现的 protocol 方法,这种方法迂回且比较容易出问题(过多操作运行时)。

现在我们可以通过更简单的方式来实现,在 hook webView 的初始化方法后,使用一对多委托方式,将 webView 的 delegate 设置为我们内部实现相关协议的对象,使得我们的 hook 代码不影响原始代码的 delegate 实现。

启发

为什么突然想到可以这样来实现功能?其实启发是来源于优秀的开源框架 WebViewJavascriptBridge ,WebViewJavascriptBridge 可以简洁优雅地实现原生和 JS 通信。

WebViewJavascriptBridge 在 Native 端实现桥接功能的简化流程是: JS 向 Native 发消息是构造特殊的 url request,由 Native 端拦截并解析 URL 请求来实现通信。那么一定会需要 webView 拦截 URL( webView:decidePolicyForNavigationAction:request:frame:decisionListener: ) 的回调来处理。

那么如何在 delegate 只能一对一传递的情况下,既保证原始的 delegate 实现,又能在 WebViewJavascriptBridge 内部实现 delegate 的回调?

走进源码

我们可以猜想,WebViewJavascriptBridge 一定使用了某种有效方式解决了这个问题。接下来让我们走进源码来看具体的实现:

1、在桥接类的初始化方法中,将 webView 实例对象传入,并设置其 delegate 为桥接类。(这时候如果外部的控制器提前设置了 delegate 会被覆盖失效)

WebViewJavascriptBridge*bridge;
_bridge =  [WebViewJavascriptBridgebridgeForWebView:webView];

2、如果调用方也想作为 delegate 代理,不能通过设置 webView 的 delegate 来实现,这样会覆盖上面桥接类的 delegate,导致桥接类无法正常工作,WebViewJavascriptBridge 的做法是将待设置 delegate 对象传入桥接类,并赋值给 _webViewDelegate (weak 变量,在 self 释放后可以随即设置为 nil,不会造成循环应用)。

[_bridge setWebViewDelegate:self];
- (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate {
    _webViewDelegate = webViewDelegate;
}

3、在桥接类对应 delegate 方法回调时,调用 _webViewDelegate 相应的实现方法,

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {

// another handler

if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) {
        [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener];
    }
}

扩展及总结

如果想实现不入侵地实现一对多 delegate,可以通过 hook webView 初始化方法以及 setDelegate 方法,并注意设置 delegate 的时机,防止被覆盖而失效。

另外,WebViewJavascriptBridge 的实现实际上是一对二的代理,虽然对我来说已经够用了。但如果有同学想扩展为一对多 delegate,可以尝试实现一个桩类,将桩类设置为 delegate,并使用数组管理其他想实现 delegate 协议的对象,实现一对多 delegate。

现在回过头看这种实现很简单易懂,但是在之前固定思维的限制下,使用了大量繁杂、迂回且不可靠的方式,所以多看这些优秀框架的源码,可以获得很多思考、设计、解决问题的思路。


以上所述就是小编给大家介绍的《iOS 一对多 delegate 的简单应用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web 2.0 Architectures

Web 2.0 Architectures

Duane Nickull、Dion Hinchcliffe、James Governor / O'Reilly / 2009 / USD 34.99

The "Web 2.0" phenomena has become more pervasive than ever before. It is impacting the very fabric of our society and presents opportunities for those with knowledge. The individuals who understand t......一起来看看 《Web 2.0 Architectures》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试