Post

Replies

Boosts

Views

Activity

Swift Data issue with a recursive model class
Dear Apple Developer Forum As the title suggests, I have an issue with Swift Data when I want to modify a property of a recursive model class instance. Please consider the following sample project: import SwiftUI import SwiftData @main struct ISSUEApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Item.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } @Model final class Item { var name: String? var parent: Item? init(name: String?, parent: Item?) { self.name = name self.parent = parent } } struct ContentView: View { @Environment(\.modelContext) private var context @Query private var items: [Item] @State private var itemToMove: Item? @State private var count: Int = 0 @State private var presentMoveView: Bool = false var body: some View { NavigationStack() { List(items, id: \.id) {item in Button(action: { itemToMove = item }, label: { Text("Id: \(item.name ?? "ERROR") and my parent iD is \(item.parent?.name ?? "root")") .bold(itemToMove == item) .italic(itemToMove == item) }) } .sheet(isPresented: $presentMoveView, content: { MoveView(toMove: self.itemToMove!) }) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { let i = Item(name: "\(count)", parent: nil) context.insert(i) try? context.save() count += 1 }, label: { Text("Add an item") }) } ToolbarItem(placement: .navigationBarLeading) { Button(action: { presentMoveView.toggle() }, label: { Text("Move selected item") }) } } } } } struct MoveView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss @Query private var items: [Item] @Bindable var toMove: Item @State private var selectedFutureParent: Item? var body: some View { NavigationStack(){ List(items, id: \.id) {item in Button(action: { selectedFutureParent = item }, label: { Text("Id: \(item.name ?? "ERROR") and my parent iD is \(item.parent?.name ?? "root")") .bold(selectedFutureParent == item) .italic(selectedFutureParent == item) }) } .toolbar(){ ToolbarItem{ Button("Move", action: { toMove.parent = selectedFutureParent dismiss() }) } } } } } #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) } Please launch the preview of this app, add items (as many as you'd like), select one and click on the "Move selected item" button. Select the new parent of the item. As you may have noticed, both selected items (moved item and new parent) are modified, whereas only one equality is used. This issue seems to be independent from the @Bindable property wrapper. I tried many things, such as using index instead of direct elements; using local let constant for the parent but the constant is still modified (very weird...) Thank you in advance for your help ! Best regards
1
0
306
Oct ’24