参与工作时间比较长了,随着 Web前端行业的发展(大家都懂得..),客户端与 Web端的交互也越来越频繁。其实本人不太喜欢依赖第三方,那种看不到摸不着的东西用起来总感觉不是很安心,同时也是为了保证双方都能够高效完成交互的途中不出现一些意料不到的异常,对此,研究了一下 JavaScriptCore这个库还是很有必要的,并分别结合 UIWebView以及 WKWebView做了一下交互总结。
<input/> 输入一个字符串,通过点击按钮设置成导航标题"以将<#字符串#>"设置成导航Title,并在网页最底下的label显示出来。分别使用 UIWebView 以及 WKWebView 实现效果如下:
类库里面有12个类(还有两个是负责导入相关类的头文件以及一个关于WebKit的宏定义);在基本的交互过程中,其实最常使用的有三个:JSContext、JSValue、JSExport
简单的理解为执行JavaScript的一个环境,就好像我们在绘制View时候需要获取的CGContext一样,JS的执行需要在此环境之下。
可以理解成 一种供iOS数据结构与JS数据结构相互转换的包装,也可以看成一种桥接关系,我们执行JS获取的结果就是通过JSValue对象进行包装传给客户端进行处理的,类型转换官方文档描述如下:

JavaScriptType返回的JSValue数据可通过JSValue.toXXX()转成客户端相应的数据结构;反之,客户端对象也可以通过JSValue()的构造方法将相应的数据结构封装成JSValue。
这是一个协议,官方文档没有暴露出任何的open协议方法,可以理解为一个空协议。
通常用法是自定义一个CustomExport : JSExport,里面将JS可以调用的属性或者方法进行暴露,JS就可以直接使用暴露的属性与方法了。
ObjC方法定义样式是非常特殊的,但官方文档给出了转换后JS调用的样式:

但这样会有一个缺点,万一,方法有很多个参,拼接起来的JS方法名简直就是日了X;不过这点Apple已经帮我们想到了,使用 JSExportAs宏,可以将方法名简化,就像 Swift中的 typealias以及 ObjC中的 typedef。

以上三个文件就算理解完了,下面来一段小应用😀。



仔细看看JSValue的类型转换,就可以知道,JS中方法就是客户端中的闭包,不过这里楼主采用了Swift和ObjC混编模式,至于原因下面会说一下:

实现方法:

Swift版本如下,功能实现在本人看来应该是一样的,但在进行注入的时候出现了问题,导致执行方法出现了undefined。


终于可以运用上面的一些方法来实现功能啦。

定义一个自定义的协议RITLJSExport,这里仍然采用混编模式,因为我还是Swfit注入失败了...

在UIWebViewDelegate
中的webViewDidFinishLoad()
方法中对JSContext进行截取,并执行操作:

首先有一点,WKWebView是获取不JSContext的,那咋办?没关系,WKWebView提供给了我们非常便利的交互,不详细说了!
添加JavaScript交互

在WKNavigationDelegate中告知web当前使用webView的类型:

履行WKScriptMessageHandler协议,完成交互操作即可

最后记得移除哦

这样子,基于JavaScriptCore的UIWebView以及WKWebView交互就算圆满完成啦!