1

I’m new to iOS development and currently learning to persist data using SwiftData. I’m building a very simple to-do list app to understand how local persistence works.

However, I’ve hit a wall and when I call context.insert(item), the new task never appears in my list, and my @Query array (items) always has a count of 0. I’ve reviewed documentation, watched tutorials, and even asked ChatGPT, but I still can’t figure out what’s missing.

Here’s my setup:

import Foundation
import SwiftData

@Model
class DataItem: Identifiable {
    var id: UUID = UUID()
    var text: String
    var isCompleted: Bool = false

    init(text: String) {
        self.text = text
    }
}


import SwiftUI

@main
struct SwiftDataIssueApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(for: DataItem.self)
    }
}
import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var context
    @Query private var items: [DataItem]
    @State private var newTask: String = ""

    var body: some View {
        NavigationView {
            List {
                ForEach(items) { item in
                    Text(item.text)
                }
            }
            .navigationTitle(Text("Tasks"))

            VStack {
                TextField("Enter New Task", text: $newTask)
                Button("Add Task", action: addTask)
            }
            .padding()
        }
    }

    func addTask() {
        let item = DataItem(text: newTask)
        context.insert(item)
        print(item.text)
        print(items.count)
        newTask = ""
    }
}

I do want to note that items.count keeps returning 0.

Does anyone know why?

7
  • items.count does not update immediately so that is expected, but the task not appearing in the list? I cannot reproduce that. Do you mean the task is not saved on the next launch? That is likely because you killed the app from Xcode and it hasn't had a chance to autosave. Commented Oct 15 at 2:29
  • It's so strange how its working for others. I don't believe I'm killing the app. I'm expecting these changes to reflect in the preview on Xcode. Commented Oct 15 at 12:15
  • I just tried testing this on my physical device and it works. Would you happen to know why it won't work on the simulator? Commented Oct 15 at 12:18
  • If you are just previewing ContentView then the .modelContainer(for: DataItem.self) you put in the WindowGroup will not do anything. Put .modelContainer(for: DataItem.self, inMemory: true) in your preview instead. Commented Oct 15 at 12:19
  • Does this work for you on the simulator? It doesn't appear to work on my end. I even tried placing .modelContainer(for: DataItem.self, inMemory: true) on the ContentView itself instead of on WindowGroup. Commented Oct 15 at 12:28

2 Answers 2

2

Remove your NavigationView, it has been deprecated for years, use NavigationStack instead.

@Model class DataItem already conforms to Identifiable, no need to do it again, it can confuse SwiftData.

Just use

     @Model
     class DataItem {
         var text: String
         var isCompleted: Bool = false

         init(text: String) {
             self.text = text
         }
     }

With these changes all works well for me.

Note, the print(items.count) will be one step behind the real items.count, because items is not updated immediately, as mentioned. But the item will appears in the List.

To see your updated items.count add this to the NavigationStack:

     .onChange(of: items.count) { 
         print("---> items.count: \(items.count)")
     }

func addTask() is not the place to have the print.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the suggestions. I really appreciate it. For some reason these changes aren't working for me. I don't understand why. Maybe it isn't the code? It's frustrating since I am not receiving an error.
I realize it only works when I test it on a physical device. Would you happen to know why it will not work on the simulator?
0

The problem I was having was getting the preview in Xcode to show changes being made to the database. The solution was to add the modelContainer to the Preview itself.


#Preview { ContentView() 
               .modelContainer(for: DataItem.self) 
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.