所以我将WKWebView
封装在UIViewRepresentable
中,并构建了一个协调器,以便访问其导航委托的功能。在webView(_:didFinish:)
函数中,我试图更新视图的didFinishLoading
变量。如果我在分配后立即打印,它将打印预期的行为。但是,在父视图中,当我调用true
函数时,它会打印getHTML
-即使我等到WKWebView完全加载。
代码如下:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
@Binding var link: String
init(link: Binding<String>) {
self._link = link
}
private var didFinishLoading: Bool = false
let webView = WKWebView()
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
self.webView.load(URLRequest(url: URL(string: self.link)!))
self.webView.navigationDelegate = context.coordinator
return self.webView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
return
}
class Coordinator: NSObject, WKNavigationDelegate {
private var webView: WebView
init(_ webView: WebView) {
self.webView = webView
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("WebView: navigation finished")
self.webView.didFinishLoading = true
}
}
func makeCoordinator() -> WebView.Coordinator {
Coordinator(self)
}
func getHTML(completionHandler: @escaping (Any?) -> ()) {
print(self.didFinishLoading)
if (self.didFinishLoading) {
self.webView.evaluateJavaScript(
"""
document.documentElement.outerHTML.toString()
"""
) { html, error in
if error != nil {
print("WebView error: \(error!)")
completionHandler(nil)
} else {
completionHandler(html)
}
}
}
}
}
struct WebView_Previews: PreviewProvider {
@State static var link = "https://apple.com"
static var previews: some View {
WebView(link: $link)
}
}
最佳答案
这是您的代码,为演示做了一些修改,ObservableObject的已用视图模型实例保持您的加载状态。
import SwiftUI
import WebKit
import Combine
class WebViewModel: ObservableObject {
@Published var link: String
@Published var didFinishLoading: Bool = false
init (link: String) {
self.link = link
}
}
struct WebView: UIViewRepresentable {
@ObservedObject var viewModel: WebViewModel
let webView = WKWebView()
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
self.webView.navigationDelegate = context.coordinator
if let url = URL(string: viewModel.link) {
self.webView.load(URLRequest(url: url))
}
return self.webView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
return
}
class Coordinator: NSObject, WKNavigationDelegate {
private var viewModel: WebViewModel
init(_ viewModel: WebViewModel) {
self.viewModel = viewModel
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("WebView: navigation finished")
self.viewModel.didFinishLoading = true
}
}
func makeCoordinator() -> WebView.Coordinator {
Coordinator(viewModel)
}
}
struct WebViewContentView: View {
@ObservedObject var model = WebViewModel(link: "https://apple.com")
var body: some View {
VStack {
TextField("", text: $model.link)
WebView(viewModel: model)
if model.didFinishLoading {
Text("Finished loading")
.foregroundColor(Color.red)
}
}
}
}
struct WebView_Previews: PreviewProvider {
static var previews: some View {
WebViewContentView()
}
}
关于swift - SwiftUI协调器未更新包含 View 的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58822960/