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
的初始化程序的末尾。
我有一个导航和详细信息视图,它发送日期字典(键)和结构数组(但结构并不重要,它包含字符串数组和其他内容。
如果我发送一个非常非常长的字典,应用程序会冻结在选定的行中,一旦列表完成加载每条记录,就会显示详细信息。
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
的初始化程序的末尾。