Swift 和 JS 交互

JavaScriptCore

JavaScriptCore 是蘋果提供的用來實現(xiàn) iOS 和 前端JS 之間的交互庫。作用是方便 Swift 調(diào)用JS方法和 JS調(diào)用 Swift 方法。

JSContext

JSContext 是Apple 提供的 JS 環(huán)境,所有的JS 語言都可以使用 evaluateScript() 直接執(zhí)行和編譯。例如:

// 通過JSContext執(zhí)行js代碼
let context: JSContext = JSContext()
let result1: JSValue = context.evaluateScript("1 + 3")
print(result1)  // 輸出4

如果在 context中定義了方法,可以通過 objectForKeyedSubscript() 獲得方法對象,再執(zhí)行方法。例如:

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

// 通過js方法名調(diào)用方法
let result2 = context.evaluateScript("sum(num1, num2)")
print(result2 as AnyObject)  // 輸出30

// 通過下標(biāo)來獲取js方法并調(diào)用方法
let squareFunc = context.objectForKeyedSubscript("sum")
let result3 = squareFunc?.call(withArguments: [10, 20]).toString()

調(diào)試 JS 代碼

JS 和 Swift 混編的情況下,調(diào)試代碼會變得比較復(fù)雜,JavaScriptCore 提供了異常處理方法。如下:

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

這樣在 JS 中存在的Bug就可以在Swift 中進(jìn)行捕獲了。

實例演示

首先,實例話WebView 來展示網(wǎng)頁。實現(xiàn)WebView 的代理方法 webViewDidFinishLoad() 獲取WebView 渲染網(wǎng)頁之后 持有的 JSContext 對象。

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

Swift 調(diào)用 JS 方法

通過上述方法獲得了 Context 對象之后,使用 objectForKeyedSubscript() 獲得方法對象,進(jìn)行調(diào)用。

JS 調(diào)用 Swift 方法

在 WebView 渲染完畢之后,需要給 JSContext 傳遞一個 繼承了 JSExport 協(xié)議的對象,這個對象中實現(xiàn)了 JS 可以調(diào)用的所有方法。具體操作如下:

func webViewDidFinishLoad(_ webView: UIWebView) {
    self.jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
    let model = SwiftJavaScriptModel() // 繼承了 JSExport 協(xié)議
    
    // 這一步是將SwiftJavaScriptModel模型注入到JS中,在JS就可以通過WebViewJavascriptBridge調(diào)用我們暴露的方法了。
    self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge" as NSCopying & NSObjectProtocol)
}

借此,在 JS 代碼中就可以通過 WebViewJavascriptBridge 進(jìn)行調(diào)用了。例如:

// 定義協(xié)議SwiftJavaScriptDelegate 該協(xié)議必須遵守JSExport協(xié)議
@objc protocol SwiftJavaScriptDelegate: JSExport {
    
    // js調(diào)用App功能 
    func record(_ orderNo: String)
}
    <div class="btn-block" onclick="WebViewJavascriptBridge.record('Hello World')">
        js調(diào)用App的方法。
    </div>

總結(jié)

這篇文章總結(jié)了如何使用 JavaScriptCore 來實現(xiàn) iOS 和 JS 之間的相互調(diào)用。這對于一些想要節(jié)省成本,只使用一套H5來適配 iOS 和 Android 端的公司來說,是一個很便捷的工具。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,199評論 4 61
  • 隨著H5技術(shù)的興起,在iOS開發(fā)過程中,難免會遇到原生應(yīng)用需要和H5頁面交互的問題。其中會涉及方法調(diào)用及參數(shù)傳值等...
    Chris_js閱讀 3,236評論 1 8
  • 注:JavaScriptCore API也可以用Swift來調(diào)用,本文用Objective-C來介紹。 在iOS7...
    JW_T閱讀 597評論 0 0
  • 我若在同一個局里跌倒多次 只因我愿 只因我傻 卻心甘
    puffmiss閱讀 195評論 0 0
  • 題目1: DOM0 事件和DOM2級在事件監(jiān)聽使用方式上有什么區(qū)別? 題目2: attachEvent與addEv...
    饑人谷_醉眼天涯閱讀 228評論 0 0

友情鏈接更多精彩內(nèi)容