Swift 和 JS 交互

JavaScriptCore

JavaScriptCore 是苹果提供的用来实现 iOS 和 前端JS 之间的交互库。作用是方便 Swift 调用JS方法和 JS调用 Swift 方法。

JSContext

JSContext 是Apple 提供的 JS 环境,所有的JS 语言都可以使用 evaluateScript() 直接执行和编译。例如:

// 通过JSContext执行js代码
let context: JSContext = JSContext()
let result1: JSValue = context.evaluateScript("1 + 3")
print(result1)  // 输出4

如果在 context中定义了方法,可以通过 objectForKeyedSubscript() 获得方法对象,再执行方法。例如:

context.evaluateScript("function sum(param1, param2) { return param1 + param2; }")

// 通过js方法名调用方法
let result2 = context.evaluateScript("sum(num1, num2)")
print(result2 as AnyObject)  // 输出30

// 通过下标来获取js方法并调用方法
let squareFunc = context.objectForKeyedSubscript("sum")
let result3 = squareFunc?.call(withArguments: [10, 20]).toString()

调试 JS 代码

JS 和 Swift 混编的情况下,调试代码会变得比较复杂,JavaScriptCore 提供了异常处理方法。如下:

jsContext.exceptionHandler = {(context, exception) in
    if let exception = exception{
        print(exception.toString())
    }
}

这样在 JS 中存在的Bug就可以在Swift 中进行捕获了。

实例演示

首先,实例话WebView 来展示网页。实现WebView 的代理方法 webViewDidFinishLoad() 获取WebView 渲染网页之后 持有的 JSContext 对象。

self.jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext

Swift 调用 JS 方法

通过上述方法获得了 Context 对象之后,使用 objectForKeyedSubscript() 获得方法对象,进行调用。

JS 调用 Swift 方法

在 WebView 渲染完毕之后,需要给 JSContext 传递一个 继承了 JSExport 协议的对象,这个对象中实现了 JS 可以调用的所有方法。具体操作如下:

func webViewDidFinishLoad(_ webView: UIWebView) {
    self.jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
    let model = SwiftJavaScriptModel() // 继承了 JSExport 协议
    
    // 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过WebViewJavascriptBridge调用我们暴露的方法了。
    self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge" as NSCopying & NSObjectProtocol)
}

借此,在 JS 代码中就可以通过 WebViewJavascriptBridge 进行调用了。例如:

// 定义协议SwiftJavaScriptDelegate 该协议必须遵守JSExport协议
@objc protocol SwiftJavaScriptDelegate: JSExport {
    
    // js调用App功能 
    func record(_ orderNo: String)
}
    
js调用App的方法。

总结

这篇文章总结了如何使用 JavaScriptCore 来实现 iOS 和 JS 之间的相互调用。这对于一些想要节省成本,只使用一套H5来适配 iOS 和 Android 端的公司来说,是一个很便捷的工具。

你可能感兴趣的:(Swift 和 JS 交互)