如何使用SwiftUI在WKWebView中注入CSS/JS?

o2g1uqev  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(334)

我是SwiftUI的新手,正尝试将一些自定义CSS/JS注入到用WKWebView加载的页面中:

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }
 
    func updateUIView(_ webView: WKWebView, context: Context) {
        let request = URLRequest(url: URL(string: "https://example.com")!)
        
        WKWebsiteDataStore.default().removeData(ofTypes: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache], modifiedSince: Date(timeIntervalSince1970: 0), completionHandler:{ })

        webView.load(request)
        webView.configuration.userContentController.addUserScript(WKUserScript( source: "alert('debug')", injectionTime: .atDocumentEnd, forMainFrameOnly: true))
    }
}

它的负载是这样的:

struct ContentView: View {
    var body: some View {
        WebView()
    }
}

遗憾的是,代码似乎并没有真正注入任何东西。我也试过在webView.load之前运行它。在谷歌上搜索了相当多,我只看到examples在UIKit中完成,不幸的是,我太缺乏经验,无法以一种可以与SwiftUI一起使用的方式 Package UIKit。
如有任何指导,将不胜感激。

yyyllmsg

yyyllmsg1#

首先,尽量避免在视图中包含业务代码。如果你想在webview内容中包含/注入JS,可以使用Webkit API中的两个函数:* EvaluateJS * 和 * AddUserScript *。您可以在"加载"开始之前使用"AddUserScript"。另外,请注意JS中的"alert"功能在当前的Mobile Safari中不起作用。您应该已经看到下面的脚本文本颜色显示为蓝色。

    • 结果:**

import SwiftUI
import WebKit

struct ContentView: View {
  var body: some View {
    VStack {
      CustomWebview()
    }
    .padding()
  }
}
struct SwiftUIWebView: UIViewRepresentable {
  typealias UIViewType = WKWebView
  
  let webView: WKWebView
  
  func makeUIView(context: Context) -> WKWebView {
    webView
  }
  func updateUIView(_ uiView: WKWebView, context: Context) {
  }
}

final class SwiftUIWebViewModel: ObservableObject {
  
  @Published var addressStr = "https://www.stackoverflow.com"
  
  let webView: WKWebView
  init() {
    webView = WKWebView(frame: .zero)
    loadUrl()
  }
  
  func loadUrl() {
    guard let url = URL(string: addressStr) else {
      return
    }
    
    webView.configuration.userContentController.addUserScript(WKUserScript( source: """
window.userscr ="hey this is prior injection";
""", injectionTime: .atDocumentStart, forMainFrameOnly: false))
    
    webView.load(URLRequest(url: url))
    // You will have the chance in 8 seconds to open Safari debugger if needed. PS: Also put a breakpoint to injectJS function.
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 8.0) {
      self.injectJS()
    }
  }
  
  func injectJS () {
    webView.evaluateJavaScript("""
      window.temp = "hey here!";
document.getElementById("content").style.color = "blue";
""")
  }
}
struct CustomWebview: View {
  
  @StateObject private var model = SwiftUIWebViewModel()
  
  var body: some View {
    VStack {
      SwiftUIWebView(webView: model.webView)
      
        .padding()
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

相关问题