SwiftUI 以异步方式加载很长的列表

SwiftUI load very long list in async way

我有一个导航和详细信息视图,它发送日期字典(键)和结构数组(但结构并不重要,它包含字符串数组和其他内容。

如果我发送一个非常非常长的字典,应用程序会冻结在选定的行中,一旦列表完成加载每条记录,就会显示详细信息。

struct DetailView: View {
    var selectedChat: [Date: [TextStruct]]? // you can try with [Date: [String]]? 

    var body: some View {

           List
           {                                    
              ForEach(self.selectedChat.keys.sorted(), id: \.self)
              { key in //section data
                  Section(header:                                                                                       
                     Text("\(self.selectedChat[key]![0].date)
                  {                                                                                                        
                        ForEach(self.selectedChat[key]!,  id:\.self) {sText in
                             // my ChatView(sText) ....                                      
                  }
               }
            }
     }

我尝试通过添加此变量在开始时加载一些行

@State private var dateAndText: [Date: [TextStruct]] = [:]

用 self.dateAndText 和 .onAppear:

替换上面的代码 (self.selectedChat)
.onAppear {
    if let chat = self.selectedChat {

           let keysDateSorted = chat.allText.keys.sorted()
           self.chatLeader = chat.chatLeader

           for key in keysDateSorted.prefix(30) {
               self.dateAndText[key] = chat.allText[key]
           }


            DispatchQueue.global(qos: .utility).async {
                 self.dateAndText = chat.allText

                 self.progressBarValue = 1
            }

       }
}

使用此解决方案,一旦我按下行,我立即可以看到前 30 条记录,没问题,但在加载所有记录之前我无法滚动。我知道只有当用户在列表末尾滚动时才可以加载数组,但如果用户不在末尾滚动,我也想加载所有列表。

所以,有一种方法可以部分加载列表(比如每 100 条记录发送和更新数组)并以异步方式加载(以免因糟糕的用户体验而冻结显示)?

您几乎可以肯定 运行 遇到了 Paul Hudson here 描述和修复的问题。

SwiftUI 正在尝试为所有更改设置动画,因此如果您使用他的 hack 来解决这个问题,它应该可以工作,但您将在列表更改之间丢失所有动画。 Apple devs 回复了他和正在 Twitter 上讨论的 Dave DeLong,他们说这绝对是他们这边的一个问题,他们希望解决。

文章的 tldr: 将 .id(UUID()) 添加到 List 的初始化程序的末尾。