SwiftUI: WKWebView не загружается - PullRequest
1 голос
/ 01 апреля 2020

У меня есть WKWebView как UIViewRepresentable в моем приложении SwiftUI, и он работает изначально. Веб-страница загружена, и я могу перейти на другие страницы. Если я заставлю веб-представление загрузить другую страницу, ничего не произойдет. Он работал с 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 не используется таким образом (упрощенный пример):

 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 Ответ

1 голос
/ 06 апреля 2020

Вы пытаетесь применить подход на основе ссылок к представлениям SwiftUI, основанным на значениях. Это не разрешено, поэтому не работает. В вашем коде использования webView в действии кнопки и ниже приведены разные независимые значения (потому что WebView имеет структуру).

Так что здесь возможен подход. Протестировано с Xcode 11.4 / iOS 13.4

demo

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
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...