有思俱乐部学习园地

swift与js之间的交互与传值


一.swift调用JS的函数:

    通过JSContext,我们有两种调用JS代码的方法 
    1:直接调用JS代码。
    2:在Swift中通过JSContext注入模型,然后调用模型的方法。
    

1.直接调用JS代码:(不推荐 其方法是在swift文件中写入JS代码)

let context = JSContext() 
context.evaluateScript(“var num = 10”)
context.evaluateScript(“function square(value) { return value * 2}”)

// 直接调用
let squareValue = context.evaluateScript(“square(num)”)
print(squareValue)

// 通过下标来获取到JS方法。
let squareFunc = context.objectForKeyedSubscript(“square”)
print(squareFunc.callWithArguments([“10”]).toString());

这种方式是没有注入模型到JS中的。这种方式使用起来不太合适,通常在JS中有很多全局的函数,为了防止名字重名,使用模型的方式是最好不过了。通过我们协商好的模型名称,在JS中直接通过模型来调用我们在Swift中所定义的模型所公开的API。

2.注入模型的交互

首先要加载JS:

func loadJS() {
        let path = Bundle.main.path(forResource: "/US.Maintenance/html/workingPersonnel/applyForMaintenance", ofType: "htm")
        /*path的 forResourse是你的htm文件所在的地址*/
        print(path)
        let url = NSURL.fileURL(withPath:path!)
        print(url)
        let request = URLRequest(url: url)
        //self.jsContext.evaluateScript("bbb",withSourceURL:url)
        view1.webView.loadRequest(request)
    }
接下来,我们在controller中在webview加载完成的代理中,给JS注入模型:
 func webViewDidFinishLoad(_ webView: UIWebView) {
        print("webViewDidFinishLoad")
        self.jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
        let model = SwiftJavaScriptModel()
        model.controller = self
        model.jsContext = self.jsContext
        self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge" as NSCopying & NSObjectProtocol)
        let path = Bundle.main.path(forResource: "/US.Maintenance/html/workingPersonnel/applyForMaintenance", ofType: "htm")
        /*path的 forResourse是你的htm文件所在的地址*/
        let url = NSURL.fileURL(withPath:path!)
        self.jsContext.evaluateScript("bbbb",withSourceURL:url)
        
        self.jsContext.exceptionHandler = { (context, exception) in
            print("exception:", exception as Any)
        }
    }   
    
    然后就可以调用JS的函数了
    @objc func success(sv:String) {
        let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("cc")
        //通过下标来调用JS的函数   cc为函数名
        let dict = ["svb": sv] as [String : Any]
        //创建字典来储存值
        _ = jsHandlerFunc?.call(withArguments:[dict])
        //通过字典传值  
        //如无参数:_ = jsHandlerFunc?.call(withArguments:)
    }
    JS文件:
    cc = function(arg){
    //arg就是我们传过来的字典
    document.getElementById('gu').innerHTML = arg['svb'];
    //通过下标svb取值
}
    

二.JS调用Swift的函数

首先,我们需要先定义一个协议,而且这个协议必须要遵守JSExport协议。
All methods that should apply in Javascript,should be in the following protocol.注意,这里必须使用@objc,因为JavaScriptCore库是ObjectiveC版本的。如果不加@objc,则调用无效果。

@objc protocol SwiftJavaScriptDelegate: JSExport {
    func up()
    func audiostart()
    func audioend()
    func audiosss()
}

接下来,我们还需要定义一个模型:(在这个协议中实现我们上面定义的函数)
@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {
    weak var controller: UIViewController?
    weak var jsContext: JSContext?
    func audiostart(){
        let audio = RecordManager()
        audio.downAction()
        print("start")
    }
    func audioend(){
        let audio = RecordManager()
        audio.upAction()
        print("end")
    }
    func audiosss() {
        let audio = RecordManager()
        audio.playAction()
    }
    func up(){
        let view22 = view2()
        view22.delegate = ViewController() as View2Delegate
        let top = UIApplication.shared.keyWindow?.rootViewController
        top?.present(view22,animated: true,completion: nil)
    }
}
接下来,我们在controller中在webview加载完成的代理中,给JS注入模型:
 func webViewDidFinishLoad(_ webView: UIWebView) {
       self.jsContext1 = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
            let model = SwiftJavaScriptModel()
            model.controller = self
            model.jsContext = self.jsContext1
             // 这一步是将OCModel这个模型注入到JS中,在JS就可以通过OCModel调用我们公暴露的方法了。
            self.jsContext1.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge" as NSCopying & NSObjectProtocol)
            let path = Bundle.main.path(forResource: "/US.Maintenance/html/workingPersonnel/applyForMaintenance", ofType: "htm")
            let url = NSURL.fileURL(withPath:path!)
            self.jsContext1.evaluateScript("bbbb",withSourceURL:url)
            self.jsContext1.exceptionHandler = { (context, exception) in
                print("exception:", exception as Any)
            }
    }   
    
然后我们就可以在JS中调用我们写好的swift函数了
audiostart = function(){
//WebViewJavascriptBridge是我们在webViewDidFinishLoad中定义的key(名字随便定义) .audiostart()是我们暴露的swift方法
    WebViewJavascriptBridge.audiostart();
}
audioend = function(){
    WebViewJavascriptBridge.audioend();
}
audiosss = function(){
    WebViewJavascriptBridge.audiosss();
}

工作人员

 
作者:丁志钢
信息录入:丁志钢