置顶
菜鸟入门,各位大佬轻喷,如有谬误之处欢迎讨论建议,也欢迎各位道友与我同行
“不积跬步,无以至千里;不积小流,无以成江海”
继续
上文中我们讨论了webview的基本使用,能展示本地的HTML或者远程的URL。
在日常的开发中,webview肯定是需要跟原生进行交互的,例如获取设备信息,调起摄像头等等HTML中不具备的能力。
所以本章我们来探讨 SwiftUI 与 webview 之间的交互。
思考
SwiftUI 与 webview 之间的交互,可以分为两种:
一种是SwiftUI向webview发送消息,上一篇文章中已经有涉及,直接调用 webview.evaluateJavascript 方法即可
另一种是 webview 主动向 SwiftUI 发送消息,SwiftUI接收到消息后执行操作,执行完毕后再进行上一种方式向 webview 发送消息。
实现
修改 webview.swift 文件
// 这是一个专门用于处理对于webview回传数据的类
class dealMessage:NSObject,WKScriptMessageHandler{
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "request" {
print("接收到消息:\(message.body)")
}
}
}
// 制定一个数据模型,这里面有webview的操作句柄
// 后续我们可以把与webview 的交互写到这个类里面
class webviewModel: ObservableObject{
let webview:WKWebView;
init() {
let config = WKWebViewConfiguration();
let userContent = WKUserContentController();
// 注入交互处理器,名称为 request
// 调用方式为 window.webkit.messageHandlers.request.postMessage("okokk")
userContent.add(dealMessage(), name: "request");
// 提前注入脚本,这里可以把交互的方法封装好提前注入HTML,以免逻辑侵入到webview中
// 这个方法可以选择注入的时机,evaluateJavascript 只能在webview初始化之后调用,当然之后再注入也可以
userContent.addUserScript(WKUserScript(source: "function changeName(){window.webkit.messageHandlers.request.postMessage('okokk')}", injectionTime: .atDocumentStart, forMainFrameOnly: false))
config.userContentController = userContent;
// 实例化 WkWebView,带上config
self.webview = WKWebView(frame: .zero,configuration: config)
// 加载本地HTML
// 这个例子加载的是本地 Resource文件夹下的 index.html
let HTMLSTRING = try! String(contentsOfFile: Bundle.main.path(forResource: "index", ofType: "html")!,encoding: .utf8)
self.webview.loadHTMLString(HTMLSTRING, baseURL: Bundle.main.resourceURL);
}
}
实现效果如下:
接收到了 webview 发出的消息
踩坑
-
HTML文件不能直接在finder中建文件夹放进去,要把整个文件夹拖入文件树,如图:
- 此后也只能在这儿改,要么就再文件树里删掉再重新导入
- evaluateJavaScript 不能紧跟初始化调用,也不能在初始化之前调用,都是无效的
- 需要注入的话要使用 addUserScript
总结
- webview 与 SwiftUI 的基本双向交互
- 本地HTML资源导入的坑,不能直接在finder 中建立文件夹使用
- 注入和执行 script 的区别
- 注意这里没有实现 webview 调用 SwiftUI 方法时的返回值,可以提前注入一个接收方法,利用promise的pending原理将发送方法封装之后再进行使用。
欢迎关注gongzhonghao【思跃喵】,一起探讨。