置頂
菜鳥入門,各位大佬輕噴,如有謬誤之處歡迎讨論建議,也歡迎各位道友與我同行
“不積跬步,無以至千裡;不積小流,無以成江海”
繼續
上文中我們讨論了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【思躍喵】,一起探讨。