内容简介:在之前我们尝试过 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 的简单应用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 袜子商店应用:一个云原生参照应用
- Android 应用中跳转到应用市场评分
- 授之以渔-运维平台应用模块一(应用树篇)
- OAM(开放应用模型)——定义云原生应用标准的野望
- ChromeOS 终端应用程序暗示其即将支持 Linux 应用
- Android应用之间数据的交互(一)获取系统应用的数据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。