Swift 與 JavaScript 的交互(經過 JavaScriotCore)

前言

此篇參考自iOS開發 - Swift使用JavaScriptCore與JS交互 做者 :天秤vs永恆html

實踐經過 JavaScriotCore 來實現 SwiftJS 的交互。
複製代碼

1、JavaScriptCore中的類

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

2、在 Swift 中調用 JS 有兩種方法。

一、直接經過 JSContext 執行 JS 代碼。

import JavaScriptCore    //記得導入JavaScriptCore


    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 multiply(param1, param2) { return param1 * param2; }")
        
    // 經過js方法名調用方法
    let result2 = context.evaluateScript("multiply(num1, num2)")
    print(result2 ?? "result2 = nil")  // 輸出200
        
    // 經過下標來獲取js方法並調用方法
    let squareFunc = context.objectForKeyedSubscript("multiply")
    let result3 = squareFunc?.call(withArguments: [10, 20]).toString()
    print(result3 ?? "result3 = nil")  // 輸出200

複製代碼

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

  1. 首先定義一個協議SwiftJavaScriptDelegate 該協議必須遵照JSExport協議
// 定義協議SwiftJavaScriptDelegate 該協議必須遵照JSExport協議
@objc protocol SwiftJavaScriptDelegate: JSExport {
    
    // js調用App的返回方法
    func popVC()
    
    // js調用App的showDic。傳遞Dict 參數
    func showDic(_ dict: [String: AnyObject])
    
    // js調用App方法時傳遞多個參數 並彈出對話框 注意js調用時的函數名
    func showDialog(_ title: String, message: String)
    
    // js調用App的功能後 App再調用js函數執行回調
    func callHandler(_ handleFuncName: String)
    
}
複製代碼
  1. 而後定義一個模型 該模型實現SwiftJavaScriptDelegate協議 (這裏注意,若是有更改 UI 的需求,那麼須要回到主線程。由於調用不在主線程)
// 定義一個模型 該模型實現SwiftJavaScriptDelegate協議
@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {
    
    weak var controller: UIViewController?
    weak var jsContext: JSContext?
    
    func popVC() {
        if let vc = controller {
            DispatchQueue.main.async {
                vc.navigationController?.popViewController(animated: true)
            }
            
        }
    }
    
    func showDic(_ 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?.present(alert, animated: true, completion: nil)
    }
    
    func callHandler(_ handleFuncName: String) {
        
        let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
        let dict = ["name": "sean", "age": 18] as [String : Any]
        let _ = jsHandlerFunc?.call(withArguments: [dict])
        
    }
}
複製代碼
  1. 而後使用WebView加載對應的網頁,這裏加載例子中的demo.html文件
func setWebView(){
        webView = UIWebView(frame: self.view.bounds)
        view.addSubview(webView)
        webView.delegate = self
        webView.scalesPageToFit = true
        
        // 測試加載本地Html頁面
        let url = Bundle.main.url(forResource: "demo", withExtension: "html")
        let request = URLRequest(url: url!)
        
        // 加載網絡Html頁面 請設置容許Http請求
        // let url = URL(string: "https://www.jianshu.com/u/50bd017bb4ba")
        // let request = URLRequest(url: url!)
        webView.loadRequest(request)
    }
複製代碼
  1. 在webViewDidFinishLoad代理中將咱們定義的模型注入到網頁中,暴露給JS
func webViewDidFinishLoad(_ webView: UIWebView) {
        
        setContext()
    }

    func setContext(){
        
        let context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
        
        let model = SwiftJavaScriptModel()
        model.controller = self
        model.jsContext = context
        
        // 這一步是將SwiftJavaScriptModel模型注入到JS中,在JS就能夠經過WebViewJavascriptBridge調用咱們暴露的方法了。
        context.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge" as NSCopying & NSObjectProtocol)
        
        // 註冊到網絡Html頁面 請設置容許Http請求
        let curUrl = self.webView.request?.url?.absoluteString  //WebView當前訪問頁面的連接 可動態註冊
        context.evaluateScript(curUrl)
        
        context.exceptionHandler = { (context, exception) in
            print("exception:", exception as Any)
        }
        
    }
複製代碼
  1. Swift與JS方法互相調用

JS調用Swift方法java

WebViewJavascriptBridge.showDic({
            'title' : '字典傳值,PierceDark 的博客',
            'description' : '歡迎交流學習',
            'url' : 'https://www.jianshu.com/u/50bd017bb4ba'
        })
複製代碼

Swift調用JS方法並傳參git

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

複製代碼

下載地址:

Github:github.com/YunyueLin/S…github

相關文章
相關標籤/搜索