我的 MacOS 应用程序使用 SwiftData 和 SwiftUI 来存储和显示食谱。当我向 SwiftData 模型添加新菜谱时,我的菜谱列表会更新。此时,我想通过更改状态变量 (selectedRecipe) 并使用 .onChange 修饰符来操作scrollTo() 命令,以编程方式滚动到新配方。但我相信滚动永远不会发生,因为列表尚未更新。
我已经使用非 SwiftData 模型进行了尝试,效果很好,所以我相当确定 SwiftData 引入了延迟。我的问题是,有没有办法知道列表更新何时完成,此时我可以安全地使用scrollTo()?
这是我的(简化的)代码:
@Environment(\.modelContext) var modelContext
var recipes: [Recipe]
@State private var selectedRecipe: UUID?
var body: some View {
NavigationSplitView {
VStack {
ScrollViewReader { proxy in
Listself.recipies, id: \.id, selection: $selectedRecipe) { recipe in
RecipeCellView(recipe: recipe)
}
.focusable()
.onAppear() {
if recipes.isEmpty == false {
self.selectedRecipe = recipes[0].id
}
}
.onChange(of: selectedRecipe) { (old, new) in
proxy.scrollTo(new, anchor: .top)
}
}
HStack {
Button { self.addRecipe()
} label: { Text("Add Recipe") }
}
}
} detail: {
if let selectedRecipe = self.selectedRecipe {
let recipe = self.searchResults.first {
$0.id == selectedRecipe }
if let toDisplay = recipe {
RecipeTabView(recipe: toDisplay)
}
}
}
}
func addRecipe() {
let myRecipe = Recipe()
modelContext.insert(myRecipe)
self.selectedRecipe = myRecipe.id
}
主要原因不是视图在数据插入之前更新。即使在
scrollTo
之前添加延迟也不会滚动。
您传递给
scrollTo
的 ID,即 new
的类型为 UUID?
,但 List
中的视图可能将 UUID
作为其 ID。类型不匹配,因此不会滚动。
使用前应拆开
new
。
if let new {
proxy.scrollTo(new, anchor: .top)
}