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)
}
    <div class="btn-block" onclick="WebViewJavascriptBridge.record('Hello World')">
        js调用App的方法。
    </div>

总结

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,291评论 4 61
  • 随着H5技术的兴起,在iOS开发过程中,难免会遇到原生应用需要和H5页面交互的问题。其中会涉及方法调用及参数传值等...
    Chris_js阅读 8,286评论 1 8
  • 注:JavaScriptCore API也可以用Swift来调用,本文用Objective-C来介绍。 在iOS7...
    JW_T阅读 3,552评论 0 0
  • 我若在同一个局里跌倒多次 只因我愿 只因我傻 却心甘
    puffmiss阅读 1,235评论 0 0
  • 题目1: DOM0 事件和DOM2级在事件监听使用方式上有什么区别? 题目2: attachEvent与addEv...
    饥人谷_醉眼天涯阅读 1,300评论 0 0