前些时间,博主遇到了一个需求,就是在网页在UIWebView显示之前传参数给web,就是webView调用OC代码的问题。那个写web页面的兄弟和博主对这个不是很熟悉。然后就是各种google,然后用了网上一个WebViewJavascriptBridge-master的库,然后整个人就开始懵B了。直到一个大神给我一个例子,看到例子以后终于搞定了,现在记录下这个过程。。。
web调OC需要用到JSContext,这个东西是干嘛的呢?以下是苹果给出解释:A JSContextobject represents a JavaScript execution environment. You create and use JavaScript contexts to evaluate JavaScript scripts from Objective-C or Swift code, to access values defined in or calculated in JavaScript, and to make native objects, methods, or functions accessible to JavaScript.我个人的理解就是它是一个web,也就相当于OC里的一个的类吧(不知道理解的对不对)。
它的创建和使用都很简单,就像这样:

我来解释下为什么要把self给context的iOS呢?看到下面的代码你就明白了:


当然,这只是OC里写的,下面看看web童鞋要怎么写,看下面:

看到了吗?这里的iOS对象就相当于ViewContrller,只要是这个ViewController遵循的协议方法,只要OC里实现了,webView都可以调用。
PS:如果在协议加上@optional关键字,web是调用不了这些方法的。
以上代码中,其实有个地方是有问题的,这个问题也是博主后来才发现的,问题的点就是:

这就会造成这个self会被强引用,最终会变成循环引用。解决是创建一个中间对象:


使用时,就这样用:

最后,这个问题还是没有完全解决,只是通过中间类替换了,这个中间类会被强引用!!!楼主,放弃了这个方法,改用WKWebView,可以点这里查看新的方案,如果还是不明白,那就看Demo吧。
网友评论
1. 可以使用我参考文章中提到的,注入一个中间的对象去交互,而不是直接使用控制器self。iOS与JS交互实战篇(ObjC版),这样可能需要在对象中在加一层代理,或者Block来进行和控制器之间的通信。
2. 注入对象改为注入类[self class],这样倒是可以防止内存泄露,但是所写的代理方法就要改为类方法,全部使用类方法在实际开发中会带来一些不便,也不会太好。
3. 使用Block进行交互替掉JSExport协议。
可能就第一个方法好用一些
@weakify_self
{
@strongify_self
context[@"iOS"] = self;
}