博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift 与 JavaScript 的交互(通过 JavaScriotCore)
阅读量:6870 次
发布时间:2019-06-26

本文共 4728 字,大约阅读时间需要 15 分钟。

前言

此篇参考自 作者 :

实践通过 JavaScriotCore 来实现 Swift 和 JS 的交互。复制代码

一、JavaScriptCore中的类

JSContext:JSContext是JS的执行环境,通过evaluateScript()方法可以执行JS代码JSValue:  JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport: JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,           在协议中声明的API都会在JS中暴露出来,这样JS才能调用原生的API复制代码

二、在 Swift 中调用 JS 有两种方法。

1、直接通过 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复制代码

2、 在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方法

WebViewJavascriptBridge.showDic({            'title' : '字典传值,PierceDark 的博客',            'description' : '欢迎交流学习',            'url' : 'https://www.jianshu.com/u/50bd017bb4ba'        })复制代码

Swift调用JS方法并传参

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

下载地址:

Github:。

转载于:https://juejin.im/post/5a955857f265da4e6f180f8d

你可能感兴趣的文章
50多种适合机器学习和预测应用的API,你的选择是?(2018年版本)
查看>>
【题目】【4天】寻宝
查看>>
Flutter教程(一) 十分钟了解Flutter
查看>>
maven实战第一步,eclipse创建hello-world项目
查看>>
安装自动化工具ansible
查看>>
手把手教你理解卷积神经网络
查看>>
本地安装sass出错问题解析
查看>>
vue项目优化--使用CDN和Gzip
查看>>
JS练习实例--编写经典小游戏俄罗斯方块
查看>>
简述Linux的启动过程
查看>>
fir.im Weekly - 如何写出零 bug 的代码
查看>>
springboot+postgresql+docker实例
查看>>
[LeetCode] Reverse Vowels of a String
查看>>
Java集合类的排序
查看>>
猴子都能看懂的《Git 分支管理》
查看>>
【面试算法】链表反转
查看>>
Git基本命令学习
查看>>
读书笔记:高性能网站建设
查看>>
镭速(Raysync)文件传输高可用安装部署介绍!
查看>>
使用 Jaeger 完成服务间的链路追踪
查看>>