置頂
菜鳥(niǎo)入門(mén),各位大佬輕噴,如有謬誤之處歡迎討論建議,也歡迎各位道友與我同行
“不積跬步,無(wú)以至千里;不積小流,無(wú)以成江海”
繼續(xù)
上文中我們討論了webview的基本使用,能展示本地的HTML或者遠(yuǎn)程的URL。
在日常的開(kāi)發(fā)中,webview肯定是需要跟原生進(jìn)行交互的,例如獲取設(shè)備信息,調(diào)起攝像頭等等HTML中不具備的能力。
所以本章我們來(lái)探討 SwiftUI 與 webview 之間的交互。
思考
SwiftUI 與 webview 之間的交互,可以分為兩種:
一種是SwiftUI向webview發(fā)送消息,上一篇文章中已經(jīng)有涉及,直接調(diào)用 webview.evaluateJavascript 方法即可
另一種是 webview 主動(dòng)向 SwiftUI 發(fā)送消息,SwiftUI接收到消息后執(zhí)行操作,執(zhí)行完畢后再進(jìn)行上一種方式向 webview 發(fā)送消息。
實(shí)現(xiàn)
修改 webview.swift 文件
// 這是一個(gè)專(zhuān)門(mén)用于處理對(duì)于webview回傳數(shù)據(jù)的類(lèi)
class dealMessage:NSObject,WKScriptMessageHandler{
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "request" {
print("接收到消息:\(message.body)")
}
}
}
// 制定一個(gè)數(shù)據(jù)模型,這里面有webview的操作句柄
// 后續(xù)我們可以把與webview 的交互寫(xiě)到這個(gè)類(lèi)里面
class webviewModel: ObservableObject{
let webview:WKWebView;
init() {
let config = WKWebViewConfiguration();
let userContent = WKUserContentController();
// 注入交互處理器,名稱為 request
// 調(diào)用方式為 window.webkit.messageHandlers.request.postMessage("okokk")
userContent.add(dealMessage(), name: "request");
// 提前注入腳本,這里可以把交互的方法封裝好提前注入HTML,以免邏輯侵入到webview中
// 這個(gè)方法可以選擇注入的時(shí)機(jī),evaluateJavascript 只能在webview初始化之后調(diào)用,當(dāng)然之后再注入也可以
userContent.addUserScript(WKUserScript(source: "function changeName(){window.webkit.messageHandlers.request.postMessage('okokk')}", injectionTime: .atDocumentStart, forMainFrameOnly: false))
config.userContentController = userContent;
// 實(shí)例化 WkWebView,帶上config
self.webview = WKWebView(frame: .zero,configuration: config)
// 加載本地HTML
// 這個(gè)例子加載的是本地 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);
}
}
實(shí)現(xiàn)效果如下:

在這里插入圖片描述
接收到了 webview 發(fā)出的消息
踩坑
-
HTML文件不能直接在finder中建文件夾放進(jìn)去,要把整個(gè)文件夾拖入文件樹(shù),如圖:
在這里插入圖片描述 - 此后也只能在這兒改,要么就再文件樹(shù)里刪掉再重新導(dǎo)入
- evaluateJavaScript 不能緊跟初始化調(diào)用,也不能在初始化之前調(diào)用,都是無(wú)效的
- 需要注入的話要使用 addUserScript
總結(jié)
- webview 與 SwiftUI 的基本雙向交互
- 本地HTML資源導(dǎo)入的坑,不能直接在finder 中建立文件夾使用
- 注入和執(zhí)行 script 的區(qū)別
- 注意這里沒(méi)有實(shí)現(xiàn) webview 調(diào)用 SwiftUI 方法時(shí)的返回值,可以提前注入一個(gè)接收方法,利用promise的pending原理將發(fā)送方法封裝之后再進(jìn)行使用。
歡迎關(guān)注gongzhonghao【思躍喵】,一起探討。
