我有一个应用程序,它最终会显示一长串数据。除了测试 Lazy Stacks、加载异步和其他技术之外,我还想提供一条加载消息。有趣的是,似乎只有最原子的视图(在这种情况下是 a Scrollview
,而不是 a List
)被重新计算。代码如下:
struct MainView: View {
@Environment(\.managedObjectContext) private var viewContext
@ObservedObject var nodeSet: NodeSet
@State private var viewIsLoaded: Bool = false
var body: some View {
VStack {
SectionBar(nodeSet: nodeSet, viewIsLoaded: $viewIsLoaded)
.frame(maxWidth: .infinity, maxHeight: 40)
Divider()
DataView(nodeSet: nodeSet, viewIsLoaded: $viewIsLoaded)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
struct DataView: View {
@Environment(\.managedObjectContext) private var viewContext
@ObservedObject var nodeSet: NodeSet
@Binding var viewIsLoaded: Bool
var body: some View {
ZStack {
ScrollView {
ForEach(nodeSet.nodes.sorted().indexed(), id: \.1.self) { index, node in
NodeView(node: node)
.onAppear{
if index+1 == nodeSet.nodes.count {
viewIsLoaded = true
print("Node List has Loaded.") // 1
}
}
}
.onAppear{ print("ForEach Loaded") } // 2
}
VStack {
Text("Loading...")
.padding()
.background(Color(.systemGray3))
.border(Color("AccentColor"))
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(.systemGray2).opacity(0.5))
.isVisible(!viewIsLoaded) // convenience view extension
}
.onAppear{ print("ZStack Loaded") } // 3
}
}
三行中的print
所有 3 行都在视图的初始加载时打印,但是当更改列表时(这就是 SectionBar 所做的,我已经删除了过滤代码),只有 #3 会在重新计算数据时打印。很明显,ForEach 和 ZStack 没有被重绘,只有 ForEach 中的单个元素。添加indexed()
感觉有点复杂,在// 1
打印之后和数据出现之前仍然有大约 1/4 秒的延迟,这让我相信那里有一个隐藏的步骤。
测试视图数据是否已加载的最可靠方法是什么,以及在行//1
和出现的视图之间发生了什么?或者,创建加载消息的更好方法是什么?
提前致谢。