Hi there,
I'm getting my bearings with SwiftData, and noticed some strange behaviour with models containing other models via arrays. When I call regular old foo.bars.append(bar)
, where foo
and bar
are both SwiftData models, the result is that bar
ends up in a random place in the bars
array, and other elements in the bars
array are potentially shuffled around.
Is there a way to override this behaviour? I'd like for append
to behave like it would in regular circumstances.
Here's a relatively minimal example:
import Foundation
import SwiftData
@Model
final class Foo {
@Relationship(deleteRule: .cascade) var bars: [Bar]
init(bars: [Bar]) {
self.bars = bars
}
}
@Model
final class Bar {
var date: Date
init(date: Date = Date()) {
self.date = date
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var foos: [Foo]
var body: some View {
NavigationStack {
List {
ForEach(foos) { foo in
ForEach(foo.bars) { bar in
Text(bar.date.formatted(date: .omitted, time: .standard))
}
Button {
withAnimation {
let bar = Bar()
modelContext.insert(bar)
foo.bars.append(bar)
}
} label: {
Text("add bar")
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
Button(action: addFoo) {
Label("Add Item", systemImage: "plus")
}
}
}
.navigationTitle("swift data test")
}
}
private func addFoo() {
withAnimation {
let newFoo = Foo(bars: [])
modelContext.insert(newFoo)
}
}
}
@main
struct SwiftDataTestApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([Foo.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
I'm well and truly a beginner, so forgive the question if the answer is entirely obvious. Thanks for your help!