SwiftUI入門(mén) - 19. webview的交互

置頂

菜鳥(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ā)出的消息

踩坑

  1. HTML文件不能直接在finder中建文件夾放進(jìn)去,要把整個(gè)文件夾拖入文件樹(shù),如圖:


    在這里插入圖片描述
  2. 此后也只能在這兒改,要么就再文件樹(shù)里刪掉再重新導(dǎo)入
  3. evaluateJavaScript 不能緊跟初始化調(diào)用,也不能在初始化之前調(diào)用,都是無(wú)效的
  4. 需要注入的話要使用 addUserScript

總結(jié)

  1. webview 與 SwiftUI 的基本雙向交互
  2. 本地HTML資源導(dǎo)入的坑,不能直接在finder 中建立文件夾使用
  3. 注入和執(zhí)行 script 的區(qū)別
  4. 注意這里沒(méi)有實(shí)現(xiàn) webview 調(diào)用 SwiftUI 方法時(shí)的返回值,可以提前注入一個(gè)接收方法,利用promise的pending原理將發(fā)送方法封裝之后再進(jìn)行使用。

歡迎關(guān)注gongzhonghao【思躍喵】,一起探討。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容