SwiftUI: не обновляйте sh приложение MacOS с пользовательским представлением - PullRequest
1 голос
/ 07 февраля 2020

Здравствуйте! Я хочу создать приложение с несколькими веб-представлениями, чтобы после их однократной загрузки я не хотел, чтобы они больше создавались заново, я хочу, чтобы они сохранили свой экземпляр.

Я создаю в своем приложении Навигация, которая включает в себя список из 10 сайтов. Когда я нажимаю на элемент списка, я хочу отобразить соответствующее веб-представление с NavigationLink. Оно работает. Но проблема в том, что если я нажму на другой элемент списка и вернусь к предыдущему, он вернется на домашнюю страницу, веб-просмотр снова загрузится. Я хочу, чтобы веб-просмотр создавался только один раз и всегда оставался в живых до тех пор, пока приложение живо. Я знаю, что swiftui всегда обновляет sh представления, это проблема, как я могу предотвратить обновление моего веб-просмотра swiftUI?

В uitkit все просто, я создаю массив wkwebview при запуске приложения, загружаю все мои URL веб-просмотра, в классе Singleton. И в зависимости от элемента, выбранного из моего табличного представления, я отображаю соответствующий wkwebview. И даже если я поменяю элемент, все мои веб-страницы будут живы, даже если мы их не увидим.

struct WebView : UIViewRepresentable {

    let request: URLRequest

    func makeUIView(context: Context) -> WKWebView  {
        let web = WKWebView()
        web.load(request)
        return web
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {

    }

}

1 Ответ

1 голос
/ 07 февраля 2020

Вот упрощенная демонстрация возможного подхода. Идея состоит в том, чтобы кэшировать созданные объекты WKWebView с помощью некоторых идентификаторов и просто повторно использовать их в созданном (или воссозданном) представлении представления в тонкой оболочке SwiftUI.

Протестировано и работает с Xcode 11.2 / iOS 13.2

struct WebView: UIViewRepresentable {

    private static var cache: [Int: WKWebView] = [:]

    // the only allowed entry point to create WebView, so have control either
    // to create new instance of WKWebView or provide already loaded
    static func view(with id: Int, request: URLRequest) -> WebView {
        var web = cache[id] // it is UI thread so safe to access static
        if web == nil {
            web = WKWebView()
            cache[id] = web
        }
        return WebView(with: web!, request: request)
    }

    private init(with web: WKWebView, request: URLRequest) {
        self.web = web
        self.request = request
    }

    private let web: WKWebView
    private let request: URLRequest

    func makeUIView(context: Context) -> WKWebView  {
        if web.url == nil { // just created, so perform initial loading
            web.load(request)
        }
        return web
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
    }
}

// Just simple test view
struct TestOnceLoadedWebView: View {
    private let urls: [String] = [
        "http://www.apple.com",
        "http://www.google.com",
        "http://www.amazon.com"
    ]

    var body: some View {
        NavigationView {
            List(0 ..< urls.count) { i in
                NavigationLink("Link \(i)", destination:
                    WebView.view(with: i, request: 
                                 URLRequest(url: URL(string: self.urls[i])!)))
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...