ForEach complaining about duplicate values with SwiftData using Unique attribute

I have a Category model that's defined like so:

@Model
final class Category {
    @Attribute(.unique) var id: UUID
    var name: String
    var parent_id: UUID? //categories can be children of other categories

    init(id: UUID, name: String, parent_id: UUID?) {
        self.id = id
        self.name = name
        self.parent_id = parent_id
    }
}

And I'm getting my categories from an API call and putting it into my View:

import SwiftUI
import SwiftData

struct CategoryView: View {
    @Environment(\.modelContext) private var modelContext
    
    @Query private var categories: [Category]
    @Query(filter: #Predicate<Category>{ $0.parent_id == nil })
        private var top_level_categories: [Category]
    
    var spacing: CGFloat = 25

    var body: some View {
        HStack() {
            Text("Categories")
                .font(.title.bold())
            
            Spacer()
            Text("see all")
        }
        .padding([.bottom, .top], 0)
        VStack(spacing: 20) {
            ScrollView(.horizontal) {
                HStack(spacing: spacing) {
                    ForEach(top_level_categories) { category in
                        Text(category.name!)

                    }
                }
            }
        }
        .onAppear{
            getCategories()
        }
    }
    
    func getCategories()  {
        get_refresh_token { token in
            guard let token = token else {
                return
            }
            var urlRequest = URLRequest (url: URL(string:"https://api.test.com/categories")!)
            urlRequest.httpMethod = "GET"
            urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
            urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
            
            URLSession.shared
                .dataTask(with: urlRequest) { (data, response, error) in
                    do {
                        if let data = data {
                            let c = try JSONDecoder().decode([Category].self, from: data)
                            c.forEach { modelContext.insert($0) }
                            try? modelContext.save()
                        }
                    }
                    catch {
                        print(error)
                    }
                }.resume()
        }
    }
}

This runs fine the first time I run the app but when I run it again, I get the following error:

ForEach<Array<Category>, UUID, Text>: the ID XXXXXX-XXXX-XXXX-XXXX-XXXXXX occurs multiple times within the collection, this will give undefined results!

Not sure why this is happening since I thought putting the @Attribute(.unique) on ID means that the same category won't get added twice?

Accepted Reply

Based on another thread, wrapping the modelContext.insert and modelContext.save in DispatchQueue.main.async fixed the issue.

Replies

Based on another thread, wrapping the modelContext.insert and modelContext.save in DispatchQueue.main.async fixed the issue.