Post

Replies

Boosts

Views

Activity

SwiftUI view not updated after SwiftData change through CloudKit
A SwiftUI view is displaying a SwiftData model object that's being updated on another device, using CloudKit. The update arrives through CloudKit and the view is correctly updated. However, when the view is not displaying the model object directly, but in a nested view, this nested view is NOT updated. Why not? Is this a bug? Or is it just me, forgetting about some elementary detail? A workaround (that I definitely don't like!) is to put a dummy SwiftData query in the nested view. Even when the dummy query result is never used, the view now IS updated correctly. Why? The code below is mostly Xcode's standard template for a SwiftUI+SwiftData+CloudKit app, modified to use a String property i.s.o. a Date, and to be able to edit that name in a Textfield. The ContentView: struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] var body: some View { NavigationSplitView { List { ForEach(items) { item in @Bindable var item = item NavigationLink { VStack(alignment: .leading) { // item details in same view TextField(item.name, text: $item.name) .textFieldStyle(.roundedBorder) .padding() .background(.red.opacity(0.5)) // item details in nested view ItemDetailView(item: item) .padding() .background(.yellow.opacity(0.5)) Spacer() } } label: { Text(item.name) } } .onDelete(perform: deleteItems) } #if os(macOS) .navigationSplitViewColumnWidth(min: 180, ideal: 200) #endif .toolbar { #if os(iOS) ToolbarItem(placement: .navigationBarTrailing) { EditButton() } #endif ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { Text("Select an item") } } private func addItem() { withAnimation { let newItem = Item(name: "item") modelContext.insert(newItem) } } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(items[index]) } } } } The nested ItemDetailView: struct ItemDetailView: View { @Bindable var item: Item // dummy query to force view updates triggered by CloudKit // @Query private var items: [Item] var body: some View { TextField(item.name, text: $item.name) .textFieldStyle(.roundedBorder) } } The result:
3
3
894
Jan ’24