SwiftUI:WKWebView无法加载

3

我在我的SwiftUI应用程序中使用WKWebView作为UIViewRepresentable,最初它是可以工作的。网页被加载并且我可以浏览到其他页面。如果我强制Web视图加载另一个页面,则不会发生任何事情。这在Xcode 11.3中有效,但似乎自从11.4以来就出现了问题。 以下是一个示例,重新加载将随机强制加载页面1或2。 有什么建议可能是问题所在吗?

import WebKit
import SwiftUI

struct WebView: UIViewRepresentable{

    var url: URL

    let urls = [URL(string: "https://google.com/")!, URL(string: "https://bing.com")!]

    private let webview = WKWebView()

    fileprivate func loadRequest() {

        let index = Int(Date().timeIntervalSince1970) % 2
        print(index)

        let request = URLRequest(url: urls[index])
        webview.load(request)
    }

    func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {

        loadRequest()

        return webview
    }

    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {}

    func reload(){
        loadRequest()
    }

}

WebView的使用方式(简化示例)如下:

WebView是这样使用的:

 var body: some View {
        VStack{
            Button(action: {
                self.webView.reload()
            }){
                Text("reload")
            }
            webView
        }
}

事情有点复杂。重新加载是由操作表触发的,似乎也存在问题。请参考我的带操作表的简化示例:

@State private var showingSheet = false
 @State private var shouldRefresh = false
    var body: some View {

            ZStack{

                WebView(url: url, reload: $shouldRefresh)
                    .padding(paddingEdgeInsets())
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
                    .edgesIgnoringSafeArea(.all)

                Button(action: {
                    self.showingSheet = true
                }){
                    Text("Show sheet")
                }



            }.actionSheet(isPresented: $showingSheet) {
                ActionSheet(title: Text("OPTIONS"), buttons: [
                    .default(Text("RELOAD"), action: {
                        self.shouldRefresh = true
                    }), .default(Text("EXIT"), action: {
                        self.presentationMode.wrappedValue.dismiss()
                    }), .cancel()])
            }
        }
1个回答

6

您尝试将“引用”方法应用于基于值的SwiftUI视图。这是不允许的,因此不起作用。在您的使用代码中,按钮操作中的webView和下面的值是不同的独立值(因为WebView是结构体)。

因此,这里有可能的方法。使用Xcode 11.4 / iOS 13.4测试通过。

演示

struct TestWebView: View {
    @State private var shouldRefresh = false
    var body: some View {
        VStack{
            Button(action: {
                self.shouldRefresh = true
            }){
                Text("Reload")
            }
            WebView(url: nil, reload: $shouldRefresh)
        }
    }
}


struct WebView: UIViewRepresentable{

    var url: URL?     // optional, if absent, one of below search servers used
    @Binding var reload: Bool

    private let urls = [URL(string: "https://google.com/")!, URL(string: "https://bing.com")!]
    private let webview = WKWebView()

    fileprivate func loadRequest(in webView: WKWebView) {
        if let url = url {
            webView.load(URLRequest(url: url))
        } else {
            let index = Int(Date().timeIntervalSince1970) % 2
            webView.load(URLRequest(url: urls[index]))
        }
    }

    func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
        loadRequest(in: webview)
        return webview
    }

    func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
        if reload {
            loadRequest(in: uiView)
            DispatchQueue.main.async {
                self.reload = false     // must be async
            }
        }
    }
}

抱歉 - URL 是我原始实现中遗留下来的。我添加了 urls 数组进行测试。问题是:webview.load(..) 没有任何作用。 - netshark1000
@netshark1000,正如我所写的,发布的代码已经经过测试并且可行。我使用的是Xcode 11.4 (11E146)版本。 - Asperi
你的意思是每次加载请求时都加载新内容,看到一次是谷歌,一次是必应?我假设你只调用这个方法一次,不去检查网页视图是否真的加载了新的 URL。 - netshark1000
@netshark1000,是的,我使用了你的快照中的actionSheet代码进行了测试,当然排除了自定义的部分。 - Asperi
让我们在聊天中继续这个讨论 - netshark1000
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接