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导航设计

Web导航设计

James Kalbach / 李曦琳 / 电子工业出版社 / 2009 年3月 / 69.80元

业务目标的实现,依赖于用户能够找到并使用您提供的服务。本书为您讲述创建有效导航系统的基本设计原则、开发技巧和实用建议,并附有大量的真实案例。本书研究深入,援引广泛,是极佳的参考资料和教学指南,适用于初级和中级网页设计师、产品经理和其他非设计职位,以及寻求全新视角的Web开发老手。一起来看看 《Web导航设计》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具