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

3

你好,我想创建一个应用程序,其中包含几个webview,在它们被加载一次后,我不希望它们再次被创建,我希望它们保持实例。

我在我的应用程序中创建了一个导航视图,其中包括一个包含10个站点的列表。当我点击列表中的项目时,我想通过NavigationLink显示相应的webview。它可以工作。但是问题是,如果我点击列表的另一个项目并返回到上一个项目,它会返回到主页,webview会重新加载。我希望webview只在应用程序存活期间创建一次,并始终保持活动状态。我知道swiftui总是刷新视图是问题所在,如何防止我的webview被swiftUI刷新?

在uitkit中,这很简单,我在应用程序启动时创建了一个wkwebview数组,加载所有我的webview url,并放入单例类中。根据从我的tableview选择的项目显示相应的wkwebview。即使我改变项目,所有我的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) {

    }

}
1个回答

8
这是一种可能的简化演示方法。思路是通过一些标识符缓存创建的 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])!)))
            }
        }
    }
}

这对处理NavigationView或NavigationSplitView旋转并始终重新加载详细视图(Web视图)也非常有效。 - aehlke

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