简体   繁体   English

SwiftUI:不要刷新自定义视图 MacOS 应用程序

[英]SwiftUI: Do not refresh a custom view MacOS app

Hello I want to create an application with several webview that once they have been loaded once, I don't want them to be recreated anymore I want them to keep their instance.您好,我想创建一个包含多个 webview 的应用程序,一旦它们被加载一次,我不想再重新创建它们,我希望它们保留它们的实例。

I create in my application A navigation view which includes a list of 10 sites.我在我的应用程序中创建了一个包含 10 个站点列表的导航视图。 When I click on a item of the list I want to display the corresponding webview with NavigationLink.当我单击列表中的一项时,我想使用 NavigationLink 显示相应的 webview。 It works.有用。 But the problem is that if I click on another item of the list and I will return to the previous one it returns to the home page, the webview loads again.但问题是,如果我点击列表中的另一项,我将返回到前一项,它会返回主页,webview 会再次加载。 I want the webview to be created only once and always stay alive in as long as the app is alive.我希望 webview 只创建一次,并且只要应用程序处于活动状态就始终保持活动状态。 I know that swiftui always refresh views is the problem, how can I prevent my webview from being refreshed by swiftUI?我知道 swiftui 总是刷新视图是问题所在,如何防止我的 webview 被 swiftUI 刷新?

In uitkit it's simple I create an array of wkwebview at launch of the app, I load all my webview url, in a singleton class.在 uitkit 中,我在应用程序启动时创建了一个 wkwebview 数组,在单例类中加载我所有的 webview url,这很简单。 And depending on the item selected from my tableview I display the corresponding wkwebview.根据从我的 tableview 中选择的项目,我会显示相应的 wkwebview。 And even if I change the item all my webview are alive even if we don't see them.即使我更改了项目,即使我们看不到它们,我的所有 webview 也仍然存在。

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) {

    }

}

Here is simplified demo of possible approach.这是可能的方法的简化演示。 The idea is to cache created WKWebView objects by some identifiers and just reuse them in created (or recreated) thin-wrapper SwiftUI view representable.这个想法是通过一些标识符缓存创建的 WKWebView 对象,并在创建(或重新创建)的瘦包装 SwiftUI 视图中重用它们。

Tested & works with Xcode 11.2 / iOS 13.2经测试适用于 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])!)))
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM