如何在 SwiftUI 中创建一个列表视图,每个列表项都是一个 WKWebView(我的实现非常慢并且有问题)

Posted

技术标签:

【中文标题】如何在 SwiftUI 中创建一个列表视图,每个列表项都是一个 WKWebView(我的实现非常慢并且有问题)【英文标题】:How to create a List view in SwiftUI with each List item being a WKWebView (my implementation is super slow and has problems) 【发布时间】:2020-08-09 05:55:36 【问题描述】:

基本上,我想在 SwiftUI 中创建一个列表视图,每个列表项都是一个 WKWebView(这就像论坛中某个主题的帖子,每个帖子数据都由一些 html 字符串表示,可能包括图片和其他内容) 类似下面的东西 something like this

但是,当我完成代码时(代码附在底部),代码执行速度超级慢,同时无法滚动。如果向下滚动,某些列表项不会加载。如果你再次向上滚动,原来加载的列表项就会消失。此外,调试窗口中有很多错误消息,例如 error

2020-08-08 22:44:15.493387-0700 WKWebViewTest[2205:76254] WF: === Starting WebFilter logging for process WKWebViewTest
2020-08-08 22:44:15.493682-0700 WKWebViewTest[2205:76254] WF: _userSettingsForUser : (null)
2020-08-08 22:44:15.493865-0700 WKWebViewTest[2205:76254] WF: _WebFilterIsActive returning: NO
2020-08-08 22:44:15.622585-0700 WKWebViewTest[2205:76254] WF: _userSettingsForUser : (null)
2020-08-08 22:44:15.622787-0700 WKWebViewTest[2205:76254] WF: _WebFilterIsActive returning: NO

我想知道如何在 SwiftUI 中很好地和快速地实现这个视图。

import SwiftUI
import WebKit

struct ContentView: View 
    init() 
        UITableView.appearance().separatorStyle = .none
        UITableViewCell.appearance().selectionStyle = .none
        UITableViewCell.appearance().backgroundColor = UIColor.clear
        UITableView.appearance().backgroundColor = UIColor.clear
    

    let htmlText = "<p>This is the paragraph</p>"
    
    var body: some View 
        List
            ForEach(0...20, id: \.self)  _ in
                VStack 
                    PostWebView(text: self.htmlText)
                        .frame(height: 50)
                    Divider()
                
            
        
        .listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    


struct PostWebView : UIViewRepresentable 
    let text: String
    
    init(text: String) 
        self.text = text
    

    class Coordinator: NSObject, WKNavigationDelegate 
        var parent: PostWebView

        init(_ parent: PostWebView) 
            self.parent = parent
        
    

    func makeCoordinator() -> Coordinator 
        Coordinator(self)
    

    func makeUIView(context: Context) -> WKWebView  
        let webview = WKWebView()
        webview.scrollView.bounces = false
        webview.scrollView.isScrollEnabled = false
        webview.navigationDelegate = context.coordinator
        let htmlStart = "<HTML><HEAD><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, shrink-to-fit=no, maximum-scale=1.0, user-scalable=no\"></HEAD><BODY>"
        let htmlEnd = "</BODY></HTML>"
        let postHtml = text
        let htmlString = "\(htmlStart)\(postHtml)\(htmlEnd)"
        webview.loadHTMLString(htmlString, baseURL:  nil)
        return webview
    

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

【问题讨论】:

【参考方案1】:

我有同样的要求,并没有使用 List,而是在 ScrollView 中使用 VStack,同时限制了每页加载的项目数(在我的例子中是 20 个)。 VStack 将渲染所有项目一次,当您向下和向上滚动时不会重新加载。因此,LazyVStack 也不起作用,因为它还会在滚动时重新加载其内容。

这也适用于自动调整 WebView 的大小以适应其加载的内容。为了视觉优化,我确保第一个项目在其他项目之前加载,出于某种奇怪的原因,SwiftUI 似乎以相反的顺序加载 webview 内容,从列表中的最新开始。

【讨论】:

以上是关于如何在 SwiftUI 中创建一个列表视图,每个列表项都是一个 WKWebView(我的实现非常慢并且有问题)的主要内容,如果未能解决你的问题,请参考以下文章

有没有更好的方法在 SwiftUI 中创建多列(数据表)列表视图

如何在 SwiftUI 中创建共享导航栏以在多个视图之间进行交互? [关闭]

在 SwiftUI 中创建一个包含自定义类数组的列表

如何在 SwiftUI 中创建核心数据管理器环境

如何在使用自定义用户代理的 SwiftUI 中创建 Safari 视图?

如何在 swiftUI 中创建具有多列的列表?