Post

Replies

Boosts

Views

Activity

Reply to [Basics] Saving in SwiftData doesn't work
Don't know if you already got your answer elsewhere but I included a working sample app below. Like mcomisso already said, to create a new entity, you have to insert it into the database using the ModelContext. let newItem = GroceryListItem(name: "New Item", stepperValue: 1) context.insert(newItem) Where you do this depends on your app. GroceryListApp.swift import SwiftUI import SwiftData @main struct GroceryListApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: GroceryListItem.self) } } GroceryListItem.swift import SwiftData @Model final class GroceryListItem { var name: String var stepperValue: Int init(name: String, stepperValue: Int = 1) { self.name = name self.stepperValue = stepperValue } } ContentView.swift import SwiftUI import SwiftData struct ContentView: View { @Environment(\.modelContext) var context @Query var groceryListItems: [GroceryListItem] @State private var newItemName: String = "" var body: some View { List { Section { TextField("New Item", text: $newItemName) Button("Add new item", action: insertNewItem) } Section { ForEach(groceryListItems) { groceryListItem in GroceryListItemView(groceryListItem: groceryListItem) } .onDelete(perform: deleteItem) } } } func insertNewItem() { let newItem = GroceryListItem(name: newItemName) context.insert(newItem) newItemName = "" } func deleteItem(at indexSet: IndexSet) { for index in indexSet { context.delete(groceryListItems[index]) } } } #Preview { ContentView() .modelContainer(for: GroceryListItem.self, inMemory: true) } GroceryListItemView.swift import SwiftUI struct GroceryListItemView: View { @Bindable var groceryListItem: GroceryListItem var body: some View { Stepper("\(groceryListItem.name) (\(groceryListItem.stepperValue)x)", value: $groceryListItem.stepperValue, in: 1...100) } } #Preview { // Note that @Previewable was introduced in the XCode 16 Beta @Previewable @State var previewItem = GroceryListItem(name: "Milk") List { GroceryListItemView(groceryListItem: previewItem) } } (I like to keep my view body clear of all logic so I extracted the @Binding and the list item into its own view.) Screenshot
Jul ’24
Reply to Context.insert() but at index 0
As far as I know, SwiftData doesn't necessarily save/query everything in the order in which they were created. So if you want to put a new object at a certain place in the list you don't know for sure if it will be saved nonetheless queried in the order you specify. A better way of approching this would be to sort the list when you query your data. If you want to sort your list by creation time, I would add a new Date attribute to your model and add a SortDescriptor to your Query. Like this: @Model final class Transcription { var text: String var creationDate: Date init(text: String, creationDate: Date) { self.text = text self.creationDate = creationDate } } struct ContentView: View { @Environment(\.modelContext) var context @Query(sort: \Transcription.creationDate, order: .reverse) var transcriptions: [Transcription] var body: some View { List { ForEach(transcriptions) { transcription in Text(transcription.creationDate.formatted(date: .abbreviated, time: .standard)) } .onDelete { indexSet in for index in indexSet { context.delete(transcriptions[index]) } } Button("Add new transcription") { context.insert(Transcription(text: "", creationDate: .now)) } } } } #Preview { ContentView() .modelContainer(for: Transcription.self, inMemory: true) }
Jul ’24