JS与原生OC/Swift相互调用总结

代码地址如下:
http://www.demodashi.com/demo/12754.html

JS-OC-Swift

JS和OC/Swift相互调用,主要总结了JS和OC交互的三种方式

1.使用UIWebView,利用JavaScriptCore实现

2.使用WKWebView,利用WKScriptMessageHandler实现

3.使用第三方框架WebViewJavascriptBridge实现

部分效果图

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);
    })
})

项目结构

JS与原生OC/Swift相互调用总结

代码地址如下:
http://www.demodashi.com/demo/12754.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

posted on   demo例子集  阅读(3046)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示