简体   繁体   中英

Load WebView inside a List without reloading webView content SwiftUI

I'm building a List that contains a webView.

List recreates views if they become visible.

My question is - if there is a way to not recreate the webView and only load it once.

I know I can use ScrollView to avoid recreation, but I need it to work with List.

In UIKit I loaded the webView outside of the cell and added it in the right indexPath in "cellForRow" function.

How can I do something similar in SwiftUI?

This is my code: List:

import SwiftUI

struct ListView: View {
    let title: String
    
    var body: some View {
        List {
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            WebView(url: URL.init(string: "https://www.google.com")!).frame(height: 300, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
        }.navigationBarTitle(title)
    }
}

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView(title: "ListView")
    }
}

WebView:

import SwiftUI
import WebKit

final class WebView : UIViewRepresentable {
    let request: URLRequest
      
    init(url: URL) {
        self.request = URLRequest(url: url)
    }
    
    func makeUIView(context: Context) -> WKWebView  {
        let view = WKWebView()
        view.scrollView.isScrollEnabled = false
        view.load(request)
        return view
    }
      
    func updateUIView(_ uiView: WKWebView, context: Context) {
        
    }
    
}

You need to use wrapper view around single WKWebView , because List can recreate/reuse any cell inside, so specific cell view is always new.

Here is possible solution. Tested with Xcode 12.1 / iOS 14.1

struct ListView: View {
    let title: String
    
    var body: some View {
        List {
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()
            LoremText()

            SingleWebView(url: URL(string: "https://www.stackoverflow.com")!).frame(height: 300)
        }.navigationBarTitle(title)
    }
}

import WebKit

struct SingleWebView : UIViewRepresentable {
    static var webView: WKWebView!
    let request: URLRequest
    
    init(url: URL) {
        self.request = URLRequest(url: url)
    }
    
    func makeUIView(context: Context) -> WKWebView  {
        if nil == Self.webView {
            Self.webView = WKWebView()
            Self.webView.scrollView.isScrollEnabled = false
        }
        if self.request.url != Self.webView.url {
            Self.webView.load(request)
        }
        return Self.webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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