Search code examples
swiftcore-dataswiftui

Updating Switfui View when CoreData changes


I'm dealing with a coredata entity with relationships. The issue is that then I append an item to the children array the UI isn't updated.

var selectedNode : Node

var body: some View {
        VStack {
            ForEach(selectedNode.childrenArray) { item in
                NavigationLink {
                    Text("Item at \(item.text!)")
                } label: {
                    Text(item.text!)
                }
            }
            
        }
        .toolbar {
            ToolbarItem {
                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }
            }
        }
        
    }
    private func addItem() {
        withAnimation {
            viewContext.performAndWait {
                let newItem = Node(context: viewContext)
                newItem.text = "Hello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello worldHello world"
                newItem.dateAdded = Date()
                
                selectedNode.addToChildren(newItem)
                do {
                    try viewContext.save()
                } catch {
                    // Replace this implementation with code to handle the error appropriately.
                    // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                }
            }
            
        }
   
}

As expected when you populate a View with the coredata array it automatically updates the view with any change in coredata. But since we are not directly using the coredata array to populate the view how should I approach updating the View.

One possible solution that came to mind was to use predicate to fetch the items that belong to the "children array", so that we can use the coredata array directly to populate the View. But I am so far unable implement this.

enter image description here


Solution

  • All CoreData Objects are ObservableObjects so they need to be wrapped in @ObservedObject so the View can be refreshed when there are changes

    @ObservedObject var selectedNode : Node
    

    Also, make sure you are using @FetchRequest or NSFetchedRequestController so the store can be observed for changes. NSFetchRequest does not observe the store.