Reputation: 3352
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.
I create in my application A navigation view which includes a list of 10 sites. When I click on a item of the list I want to display the corresponding webview with NavigationLink. 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. I want the webview to be created only once and always stay alive in as long as the app is alive. I know that swiftui always refresh views is the problem, how can I prevent my webview from being refreshed by 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. And depending on the item selected from my tableview I display the corresponding wkwebview. And even if I change the item all my webview are alive even if we don't see them.
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) {
}
}
Upvotes: 3
Views: 1287
Reputation: 258423
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.
Tested & works with 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])!)))
}
}
}
}
Upvotes: 8