iOS開發 - Swift使用JavaScriptCore與JS交互

1、前言

在這個提倡敏捷開發和H5橫行的年代,原生App內嵌入一些H5頁面已經成爲一種流行的趨勢。一套H5頁面就能夠適配複雜的iOS和Android頁面,大量節省了開發和維護時間,若是原本就有移動端網頁,只需簡單適配便可完成,那咱們何樂而不爲呢?蘋果也順應了潮流,在iOS7中提供了JavaScriptCore框架用來與網頁中的JS進行交互。還有Facebook推出的React Native,也給跨平臺開發提供了新的思路和解決方案,雖然目前它還不是很成熟。但做爲一個開發者,對這些新技術的出現天然會感到無比的興奮。本文主要介紹iOS開發中,Swift如何使用JavaScriptCore與網頁中的JS進行交互。javascript

下載地址:

Github:https://github.com/YanlongMa/SwiftJavaScriptCore
若是本Demo對您有幫助,請不要吝嗇您的Start(⊙o⊙)哦。html

2、JavaScriptCore中的類

  • JSContext:JSContext是JS的執行環境,經過evaluateScript()方法能夠執行JS代碼
  • JSValue:JSValue封裝了JS與ObjC中的對應的類型,以及調用JS的API等
  • JSExport:JSExport是一個協議,遵照此協議,就能夠定義咱們本身的協議,在協議中聲明的API都會在JS中暴露出來,這樣JS才能調用原生的API

3、交互方式主要有兩種

一)、 在Swift中,經過JSContext直接執行JS代碼

import JavaScriptCore    //記得導入JavaScriptCore


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

// 定義js變量和函數
context.evaluateScript("var num1 = 10; var num2 = 20;")
context.evaluateScript("function sum(param1, param2) { return param1 + param2; }")

// 經過js方法名調用方法
let result2 = context.evaluateScript("sum(num1, num2)")
print(result2)  // 輸出30

// 經過下標來獲取js方法並調用方法
let squareFunc = context.objectForKeyedSubscript("sum")
let result3 = squareFunc.callWithArguments([10, 20]).toString()
print(result3)  // 輸出30

二). 在Swift中經過JSContext注入模型,而後調用模型的方法

1. 首先定義定義協議SwiftJavaScriptDelegate 該協議必須遵照JSExport協議

@objc protocol SwiftJavaScriptDelegate: JSExport {

    // js調用App的微信支付功能 演示最基本的用法
    func wxPay(orderNo: String)

    // js調用App的微信分享功能 演示字典參數的使用
    func wxShare(dict: [String: AnyObject])

    // js調用App方法時傳遞多個參數 並彈出對話框 注意js調用時的函數名
    func showDialog(title: String, message: String)

    // js調用App的功能後 App再調用js函數執行回調
    func callHandler(handleFuncName: String)

}

2. 而後定義一個模型 該模型實現SwiftJavaScriptDelegate協議

@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {

    weak var controller: UIViewController?
    weak var jsContext: JSContext?

    func wxPay(orderNo: String) {

        print("訂單號:", orderNo)

        // 調起微信支付邏輯
    }

    func wxShare(dict: [String: AnyObject]) {

        print("分享信息:", dict)

        // 調起微信分享邏輯
    }

    func showDialog(title: String, message: String) {

        let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "肯定", style: .Default, handler: nil))
        self.controller?.presentViewController(alert, animated: true, completion: nil)
    }

    func callHandler(handleFuncName: String) {

        let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
        let dict = ["name": "sean", "age": 18]
        jsHandlerFunc?.callWithArguments([dict])
    }
}

3. 而後使用WebView加載對應的網頁,這裏加載例子中的demo.html文件

func addWebView() {

    self.webView = UIWebView(frame: self.view.bounds)
    self.view.addSubview(self.webView)
    self.webView.delegate = self
    self.webView.scalesPageToFit = true

    // 加載本地Html頁面
    let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
    let request = NSURLRequest(URL: url!)

    // 加載網絡Html頁面 請設置容許Http請求
    //let url = NSURL(string: "http://www.mayanlong.com");
    //let request = NSURLRequest(URL: url!)

    self.webView.loadRequest(request)
}

4. 最後在webViewDidFinishLoad代理中將咱們定義的模型注入到網頁中,暴露給JS

func webViewDidFinishLoad(webView: UIWebView) {


    self.jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    let model = SwiftJavaScriptModel()
    model.controller = self
    model.jsContext = self.jsContext

    // 這一步是將SwiftJavaScriptModel模型注入到JS中,在JS就能夠經過WebViewJavascriptBridge調用咱們暴露的方法了。
    self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge")

    // 註冊到本地的Html頁面中
    let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
    self.jsContext.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding))

    // 註冊到網絡Html頁面 請設置容許Http請求
    //let url = "http://www.mayanlong.com";
    //let curUrl = self.webView.request?.URL?.absoluteString    //WebView當前訪問頁面的連接 可動態註冊
    //self.jsContext.evaluateScript(try? String(contentsOfURL: NSURL(string: url)!, encoding: NSUTF8StringEncoding))

    self.jsContext.exceptionHandler = { (context, exception) in
        print("exception:", exception)
    }
}

5. Swift與JS方法互相調用

JS調用Swift方法

WebViewJavascriptBridge.wxPay('TN20160526')

WebViewJavascriptBridge.wxShare({
            'title' : '馬燕龍我的博客',
            'description' : '一個專一於編程的技術博客',
            'url' : 'http://www.mayanlong.com'
        })

WebViewJavascriptBridge.showDialogMessage('馬燕龍我的博客', '一個專一於編程的技術博客')

Swift調用JS方法並傳參

func callHandler(handleFuncName: String) {

    let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
    let dict = ["name": "sean", "age": 18] jsHandlerFunc?.callWithArguments([dict]) }

這樣,咱們就實現了Swift與JS的交互了,Demo中給出了詳細的代碼,你們能夠下載運行。java

4、代碼下載及效果圖

下載地址:

Github:https://github.com/YanlongMa/SwiftJavaScriptCore
若是本Demo對您有幫助,請不要吝嗇您的Start(⊙o⊙)哦。git

效果圖:

Swift與JS交互效果

本文首發於馬燕龍我的博客,歡迎分享,轉載請標明出處。
馬燕龍我的博客:http://www.mayanlong.com
馬燕龍我的微博:http://weibo.com/imayanlong 
馬燕龍Github主頁:https://github.com/yanlongmagithub

相關文章
相關標籤/搜索