天天看點

SwiftUI入門 - 19. webview的互動

置頂

菜鳥入門,各位大佬輕噴,如有謬誤之處歡迎讨論建議,也歡迎各位道友與我同行
“不積跬步,無以至千裡;不積小流,無以成江海”

繼續

上文中我們讨論了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);
    }
}

           

實作效果如下:

SwiftUI入門 - 19. webview的互動

接收到了 webview 發出的消息

踩坑

  1. HTML檔案不能直接在finder中建檔案夾放進去,要把整個檔案夾拖入檔案樹,如圖:
    SwiftUI入門 - 19. webview的互動
  2. 此後也隻能在這兒改,要麼就再檔案樹裡删掉再重新導入
  3. evaluateJavaScript 不能緊跟初始化調用,也不能在初始化之前調用,都是無效的
  4. 需要注入的話要使用 addUserScript

總結

  1. webview 與 SwiftUI 的基本雙向互動
  2. 本地HTML資源導入的坑,不能直接在finder 中建立檔案夾使用
  3. 注入和執行 script 的差別
  4. 注意這裡沒有實作 webview 調用 SwiftUI 方法時的傳回值,可以提前注入一個接收方法,利用promise的pending原理将發送方法封裝之後再進行使用。

歡迎關注gongzhonghao【思躍喵】,一起探讨。