美文网首页
webviewTojs

webviewTojs

作者: alex_zn | 来源:发表于2018-07-19 14:34 被阅读0次

要点

native -> js
主要是通过 直接 执行一段 js 函数代码

1,context.evaluateScript("SwiftFunc()")//异步

2, webView.stringByEvaluatingJavaScriptFromString("SwiftFunc()")//同步

//同步

js -> native

1.通过context?.setObject(unsafeBitCast(temp, to: AnyObject.self), forKeyedSubscript: "test2" as (NSCopying & NSObjectProtocol)!)

2,通过新建model后 通过 setObject注入model, 而model要实现protocol,protocol是要 执行的方法。 在js中onclick 中 实现 model.func()

swift文件

  // Swift 调用JS 方法 (无参数)
    @IBAction func swift_js_pargram(_ sender: AnyObject) {
        
        _ = self.context?.evaluateScript("Swift_JS1()")
//        self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS1()") // 此方法也可行
    }
    
    // Swift 调用JS 方法 (有参数)
    @IBAction func swift_js_nopargam(_ sender: AnyObject) {
        
        _ = self.context?.evaluateScript("Swift_JS2('oc' ,'Swift')")
//        self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS2('oc','swift')") // 此方法也可行
    }
    
    func menthod1() {
        print("JS调用了无参数swift方法")
    }
    
    func menthod2(_ str1: String, str2: String) {
        print("JS调用了有参数swift方法:参数为\(str1),\(str2)")
    }
    
    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        print(error)
    }
    
}

extension ViewController: UIWebViewDelegate {
    
    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        
        return true
    }
    
    func webViewDidStartLoad(_ webView: UIWebView) {
        
        print("webViewDidStartLoad----")
        
    }
    
    func webViewDidFinishLoad(_ webView: UIWebView) {
        
        print("webViewDidFinishLoad----")
        self.context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext
        
        // JS调用了无参数swift方法
        let temp1: @convention(block) () ->() = {
            
            self.menthod1()
        }
        
        self.context?.setObject(unsafeBitCast(temp1, to: AnyObject.self), forKeyedSubscript: "showAlart1" as (NSCopying & NSObjectProtocol)!)
        
        // JS调用了有参数swift方法
        let temp2: @convention(block) () ->() = {
            
            let array = JSContext.currentArguments() // 这里接到的array中的内容是JSValue类型
            
            for object in array! {
                print(object)
            }
            
            self.menthod2((array?[0] as AnyObject).toString(), str2: (array?[1] as AnyObject).toString())
        }
        
        self.context?.setObject(unsafeBitCast(temp2, to: AnyObject.self), forKeyedSubscript: "test2" as (NSCopying & NSObjectProtocol)!)
        
        // 模型注入的方法
        let model = JSObjCModel()
        model.controller = self
        model.jsContext = context
        
        // 这一步是将OCModel这个模型注入到JS中,在JS就可以通过OCModel调用我们暴露的方法了。
        context?.setObject(model, forKeyedSubscript: "OCModel" as (NSCopying & NSObjectProtocol)!)
        

    }
}

@objc protocol JavaScriptSwiftDelegate: JSExport {
    func callSystemCamera()
    
    func showAlert(_ title: String, msg: String)
    
    func callWithDict(_ dict: [String: AnyObject])
    
    func jsCallObjcAndObjcCallJsWithDict(_ dict: [String: AnyObject])
}

@objc class JSObjCModel: NSObject, JavaScriptSwiftDelegate ,UIImagePickerControllerDelegate,UIActionSheetDelegate,UINavigationControllerDelegate {
    
    weak var controller: UIViewController?
    weak var jsContext: JSContext?
    
    func callSystemCamera() {
        
        print(controller.debugDescription)
        
        let imagePickerController:UIImagePickerController = UIImagePickerController()
        imagePickerController.delegate = self
        
        imagePickerController.allowsEditing = true//true为拍照、选择完进入图片编辑模式
        imagePickerController.sourceType = .camera

        
        controller?.present(imagePickerController, animated: true, completion: nil)
//        let jsFunc = self.jsContext?.objectForKeyedSubscript("jsFunc");
//        _ = jsFunc?.call(withArguments: []);
    }
    
    func showAlert(_ title: String, msg: String) {
        
        DispatchQueue.main.async { () -> Void in
            let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "ok", style: .default, handler: nil))
            self.controller?.present(alert, animated: true, completion: nil)
        }
    }
    
    // JS调用了我们的方法
    func callWithDict(_ dict: [String : AnyObject]) {
        print("js call objc method: callWithDict, args: %@", dict)
    }
    
    // JS调用了我们的又去
    func jsCallObjcAndObjcCallJsWithDict(_ dict: [String : AnyObject]) {
        print("js call objc method: jsCallObjcAndObjcCallJsWithDict, args: %@", dict)
        
//        let jsParamFunc = self.jsContext?.objectForKeyedSubscript("jsParamFunc");
//        let dict = NSDictionary(dictionary: ["age": 18, "height": 168, "name": "lili"])
//        
//        _ = jsParamFunc?.call(withArguments: [dict])
//        
//        _ = JSContext.currentArguments()
        

        let url = Bundle.main.url(forResource: "rc_ac_audio_file_icon.png", withExtension: nil)
        let data = NSData.init(contentsOf: url!)
        
        let jsPar = jsContext?.objectForKeyedSubscript("showImgFunc");
//        let argument = image as? NSData ?? NSData()
        
        _ = jsPar?.call(withArguments: [data!])
        
    }
    
    //
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        
//        let image = info[UIImagePickerControllerEditedImage] //as? UIImage ?? UIImage()
//        
//        let jsPar = jsContext?.objectForKeyedSubscript("jsParamFunc");
//        let argument = image as? NSData ?? NSData()
//        
//        _ = jsPar?.call(withArguments: [argument])
//        
        
    }
html文件
<button type="button" onclick="JS_Swift1()">JS调用Swift方法(无参)</button> </br>
<button type="button" onclick="JS_Swift2()">JS调用Swift方法(传参)</button>
           
           <!--      模型注入     -->
           <b>model 注入</b>
           
           <div style="margin-top: 100px">
               
                <input type="button" value="Call ObjC system camera" onclick="OCModel.callSystemCamera()">
                <input type="button" value="Call ObjC system alert" onclick="OCModel.showAlertMsg('js title', 'js message')">
                    
           </div>
           </hr>
           
           <div>
               
               <input type="button" value="Call ObjC func with JSON " onclick="OCModel.callWithDict({'name': 'testname', 'age': 10, 'height': 170})">
                   <input type="button" value="Call ObjC func with JSON and ObjC call js func to pass args." onclick="OCModel.jsCallObjcAndObjcCallJsWithDict({'name': 'testname', 'age': 10, 'height': 170})">
           </div>
           
           <div bgcolor="#ddd0">
               <span id="jsParamFuncSpan" style="color: red; font-size: 50px;">interHtml</span>
           </div>
           
           <div bgcolor="#0000">
               <img id="imgShowDiv" src="" width="300px" height="300px" style="display: block;" />
            </div>
           
           <script type="text/javascript">
               
               function jsFunc() {
                   alert('Objective-C call js to show alert');
               }
           // 注意哦,如果JS写错,可能在OC调用JS方法时,都会出错哦。
           var jsParamFunc = function(argument) {
               
               document.getElementById('jsParamFuncSpan').innerHTML
               = argument['name'];
           }

相关文章

  • webviewTojs

    要点 native -> js主要是通过 直接 执行一段 js 函数代码 1,context.evaluateSc...

网友评论

      本文标题:webviewTojs

      本文链接:https://www.haomeiwen.com/subject/ydltmftx.html