你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
首页
热门
推荐
精选
登录
|
注册
JS与原生OC/Swift相互调用总结
立即下载
用AI写一个
金额:
1
元
支付方式:
友情提醒:源码购买后不支持退换货
立即支付
我要免费下载
发布时间:2018-03-30
6人
|
浏览:4877次
|
收藏
|
分享
技术:object-c+Swift
运行环境:xcode 9
概述
JS和OC/Swift相互调用,主要总结了JS和OC交互的三种方式
详细
# JS-OC-Swift JS和OC/Swift相互调用,主要总结了JS和OC交互的三种方式 1.使用UIWebView,利用**JavaScriptCore**实现 2.使用WKWebView,利用**WKScriptMessageHandler**实现 3.使用第三方框架[WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge)实现 ## 部分效果图 ![](/contentImages/image/20180329/sC0Ura6f25NfSRn2oyy.png) ## JavaScriptCore **JavaScriptCore介绍** JavaScriptCore框架是基于webkit中以C/C++实现的JavaScriptCore的一个包装,该框架让Objective-C和JavaScript代码直接的交互变得更加的简单方便,主要由下面几个类组成。 **1.JSContext ** JS执行的环境,同时也通过JSVirtualMachine管理着所有对象的生命周期,每个JSValue都和JSContext相关联并且强引用context。可以通过[webView valueForKeyPath:@”documentView.webView.mainFrame.javaScriptContext”]来从webview上获取相应的JSContext。 **2.JSValue ** JS对象在JSVirtualMachine中的一个强引用,其实就是Hybird对象。我们对JS的操作都是通过它。并且每个JSValue都是强引用一个context。同时,OC和JS对象之间的转换也是通过它。 **3.JSManagedValue ** JS和OC对象的内存管理辅助对象。由于JS内存管理是垃圾回收,并且JS中的对象都是强引用,而OC是引用计数。如果双方相互引用,势必会造成循环引用,而导致内存泄露。我们可以用JSManagedValue保存JSValue来避免。 **4.JSVirtualMachine ** JS运行的虚拟机,有独立的堆空间和垃圾回收机制。 **5.JSExport ** 一个协议,如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。 在Swift中获取JS的context ``` context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext ``` 注入JS需要的对象,对象命名与html中使用的保持一致.`self`是遵守了JSExport协议,也可是其他遵守协议的对象。 ``` context?.setObject(self, forKeyedSubscript: "OC" as NSCopying & NSObjectProtocol) ``` JS调用Swift的方法,在Swift中实现协议 ``` @objc protocol JSDelegate :JSExport { //包含参数的func,需要注意参数名对函数名称的影响 func showMessageToYou(_ message:String) /* 对应html中“showAAndB”,此方法包含两个参数,需要在参数前加“_” func showA(_ aString: String, andB: String) func showAAndB(_ aString:String,_ bStr:String) 以上两个方法等同 */ func showAAndB(_ aString:String,_ bStr:String) func doActionCallBack() } ``` Swift调用JS的方法 ``` let jsStr = String(format:"callback('%@')",(textField?.text)!) self.context?.evaluateScript(jsStr) ``` OC中可使用block和实现JSExport协议两种方式实现,代码实现: ``` JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.context = context; //注入JS需要的“OC”对象,该对象与html中的保持一致即可 self.context[@"OC"] = self; ``` ## WKScriptMessageHandler 初始化WKWebView后,添加供js调用oc/Swift的桥梁,这里的name对应WKScriptMessage中的name ``` webView.configuration.userContentController.add(_ scriptMessageHandler: WKScriptMessageHandler, name: String) ``` 遵守协议WKScriptMessageHandler,实现以下方法,可实现JS把消息发送给OC/Swift。 ``` func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) ``` OC/Swift调用JS ``` let jsStr = String(format:"callback('%@')",(textField?.text)!) self.webView.evaluateJavaScript(jsStr as String, completionHandler: { (result:Any?, error:Error?) in print("error:",error as Any) }) ``` ## WebViewJavascriptBridge WebViewJavascriptBridge是一个Objective-C与JavaScript进行消息互通的第三方库,可以很方便的实现OC和Javascript互调的功能。WebViewJavascriptBridge实现互调的过程也容易理解,就是在OC环境和Javascript环境各自保存一个相互调用的bridge对象,每一个调用之间都有id和callbackid来找到两个环境对应的处理。从Github上下载源码之后,可以看到核心类主要包含如下几个: **WebViewJavascriptBridge_JS:**Javascript环境的Bridge初始化和处理。负责接收OC发给Javascript的消息,并且把Javascript环境的消息发送给OC。 **WKWebViewJavascriptBridge/WebViewJavascriptBridge:**主要负责OC环境的消息处理,并且把OC环境的消息发送给Javascript环境。 **WebViewJavascriptBridgeBase:**主要实现了OC环境的Bridge初始化和处理。 初始化WKWebViewJavascriptBridge ``` self.webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView]; [self.webViewBridge setWebViewDelegate:self]; ``` JS调用OC需要注册事件 ``` [self.webViewBridge registerHandler:@"handlerName" handler:^(id data, WVJBResponseCallback responseCallback) { //code }]; ``` OC调用JS ``` [self.webViewBridge callHandler:@"handlerName" data:@[textField.text] responseCallback:^(id responseData) { NSLog(@"%@",responseData); }]; ``` html中需要放置以下代码 ``` /*这段代码是固定的,必须要放到js中*/ function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } /*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/ setupWebViewJavascriptBridge(function(bridge) { bridge.registerHandler('callback', function(data, responseCallback) { callback(data); responseCallback('js执行过了'+data); }) }) ``` ## 项目结构 ![](/contentImages/image/20180329/bauuoZh5WOGkFcJ3h4A.png)
本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
感谢
1
手机上随时阅读、收藏该文章 ?请扫下方二维码
相似例子推荐
评论
作者
Elina
3
例子数量
31
帮助
4
感谢
评分详细
可运行:
4.5
分
代码质量:
4.5
分
文章描述详细:
4.5
分
代码注释:
4.5
分
综合:
4.5
分
作者例子
iOS仿支付宝首页的刷新布局效果
JS与原生OC/Swift相互调用总结
KINavigationController使用演示例子