ObjC & JavaScript 交互,在恰当的时机注入对象

11545755-bf408dd07f8806f9

移动端项目开发中,免不了出现 Native App (以下简称Native)和 H5 页面(以下简称H5)的交互,网络上有很多第三方框架,比如WebViewJavascriptBridge,对于一些小的项目需求来说,其实不用那么麻烦,我们还是<!–more–>先从基础着手。

先了解几个基础方法

  • 网页即将加载(最先执行的代理方法),在每次load 页面的时候都会先走这个回调,可以在此做一些自己的操作,经常会在这儿拦截协议

  • 网页已经加载完成(最后执行的代理方法),执行到这个地方,web 页面已经加载完成,相关代码也都执行完毕

根据不同的场景,找一个最合适的方法

场景1

(H5 通信 Native,告知Native 要做的事儿)

需求分析:

这应该不是最简单的一个需求,最简单的是Native 通过url 给H5 页面传参数,告知H5 要做的事儿。

这个需求中,H5 页面已经加载完毕,此时可以说H5 页面相关的Bug 和UI 缺陷都与Native 无关,我每次都是这么跟测试人员讲,类似问题直接assign 给他们。

功能实现:

对于这类比较简单的需求,最常用的做法就是,通过拦截协议的方法,在点击标签的时候,可以调用自定义协议的超链接,比如定义一个 yuhanle://action/close的链接,在页面即将load 的时候,判断url 的协议,如果协议是 yuhanle,就拦截掉这个请求,做自己的处理。

图解:

12545755-9a66b0a332873951

场景2

(H5 调用 Native App 的JS 方法,包括同步和异步操作)

需求分析:

这个需求中肯定需要Native 注入JS 方法,H5 通过调用JS 和Native 通信,其中包括同步和异步两种情况下的处理,需要注意的就是异步操作时,H5 需要在调用 App 时传入一个 JS 方法名,App 在拿到数据后可以回调 H5 的JS 方法,在调用这个回调的时候,需要使用webView 的currentThread,不然就会出现页面卡死。

功能实现:

1- 定义一个类,用于注入这个对象

2- 声明协议,实现和JS 对应的方法

3- 我们需要在打开webView 的时候,找到一个好的时机注入 JS

4- 对应H5 页面的JS 定义及调用

Test how to use objective-c call js

Click to next page

按照以上的做法,就能达到Native 和H5 之间的相互通信,现在的问题是,在什么时候注入JS 对象,才能满足H5 页面的需求,因为实际情况中,H5 页面可能会随时调用你的JS。

需要注意的几个问题

1- 场景2 中我们提到的,异步调用时的线程问题 首先看下下面的代码

这段代码,就是想在H5 页面调用的时候,App 这边自动登陆,重新获取到最新的token,拿到结果以后并回调H5,整个过程上是异步的,看起来是没问题的,但是一旦实际操作起来,会在这里卡死。具体原因,我也不好解释,解决办法是有的,只能通过webView 的currentThread 来执行perform 操作。

示例如下:

2- 同样是场景2 中的一个问题,什么时候注入对象

需求总是虚无缥缈的,对于H5 结合 Native 的开发结构中,Native 始终扮演着服务和入口的角色,H5 可能随时都会主动和Native 通信,但是Native 应该在什么时候准备好这些服务呢?

看了很多网上的资料,几乎全部都是在页面加载完成 webViewDidFinishLoad 这个回调中注入方法,但实际开发中,很多页面在加载的时候就需要和Native 通信,比如说拿到token,如果在这个时候才注入,肯定是来不及的,只能无功而返。

相信大多数人都没太在意这个问题,当然,如果强制让H5 的开发人员修改逻辑,将所有的通信都放在页面加载完成以后在做,也没问题,只不过对于用户的体验会变得糟糕。

深入研究官方文档,就会发现,webView 在加载过程中,会执行这么一个方法,他的作用是

13545755-08dab112b16f82f0

具体参见官方文档说明 didCreateJavaScriptContext

看到这里,我们就能在收到这个消息的时候,拿到JSContext,然后注入我们的Model。

首先,新建一个NSObject 的Catagory,在这个代理方法中发送一个通知

然后,在webView 的控制器中监听这个消息

实现@selector 方法

如此,应该是一次比较完美的注入了~

1 2 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部