Xcode 16.1(macOS 15.1)上带有 SwiftUI 和 SwiftData 的多平台应用程序的样板代码有一个包含 NavigationLinks 列表的 NavigationSplitView。当 NavigationLink 内容是标准 SwiftUI 小部件(如文本)时,该小部件会在选择列表中的不同项目时更新。但是,如果我尝试将自定义视图(下面代码中的 DetailView())添加到 NavigationLink 内容,则在选择列表中的不同项目时不会更新该自定义视图。在预览画布中运行并运行构建时会看到相同的行为。
这是代码。除了添加 DetailView 实现和在 NavigationLink 内容中添加 DetailView 外,其余都是 Xcode 样板。
有人能帮助我理解为什么 DetailView 从未随着列表选择的变化而更新吗?
import SwiftUI
import SwiftData
@Model
final class Item {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
var stringVal: String {
timestamp.formatted(date: .numeric, time: .complete)
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
var body: some View {
NavigationSplitView {
List {
ForEach(items) { item in
NavigationLink {
// DetailView does NOT update with list selection change
DetailView(item: item)
.foregroundStyle(.red)
Divider()
// Text DOES update with list selection change
Text(item.stringVal)
.foregroundStyle(.blue)
}
} label: {
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
}
.navigationSplitViewColumnWidth(min: 180, ideal: 200)
.toolbar {
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
} detail: {
Text("Select an item")
}
}
private func addItem() {
withAnimation {
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
}
}
#Preview {
ContentView()
.modelContainer(for: Item.self, inMemory: true)
}
struct DetailView: View {
@State var item: Item
var body: some View {
Text(item.stringVal)
}
}
DetailView.item
不应该是@State
。只需删除@State
@State
s在整个视图生命周期内只会被初始化一次@State
,并且您无法从外部更新 a。这就是为什么强烈建议@State
属性应该是 的原因private
,这样您就不会通过自动生成的成员初始化程序意外地将值传递给它(这几乎总是不会按照您的预期执行)。此外,这不是使用 的记录方式
NavigationSplitView
,我不知道它是否会在将来中断。NavigationSplitView
应该由 驱动。详细视图应始终放置在视图构建selection
器中。例如:List
detail: