dddddeano
dddddeano

Reputation: 9

What am i doing wrong here, My UI should be refreshing when a CoreData Object is updated

I'm working on SwiftUI, With CoreData, I have Group.entity that can have many Items.entity.

Clicking on group navigates to a list of items in said group. you click the star to Toggle its fill, like with a "Favorites"

my system works 100% however to see the change i need to navigate BACK out and in again.

from my research - CoreData Objects work like observable objects, and FetchRequests are LIVE as in they tell a view that data has change and its time to refresh the LIST or the FOREACH.

struct ContentView: View {
@Environment(\.managedObjectContext) var moc

@FetchRequest(entity: Group.entity(), sortDescriptors: [])
var groups: FetchedResults<Group>

@FetchRequest(entity: Item.entity(), sortDescriptors: [])
var items: FetchedResults<Item>

var body: some View {
    NavigationView {
        VStack {
            AddDummyDataButton()
            List {
                ForEach(groups, id: \.self) { group in
                    NavigationLink(destination: GroupDetail(group: group)) {
                        Text(group.wrappedName)
                    }
                }.onDelete { IndexSet in
                    let deleteItem = self.groups[IndexSet.first!]
                    self.moc.delete(deleteItem)
                    try? self.moc.save()
                }
            }
        }
    }
}
}
struct GroupDetail: View {
@Environment(\.managedObjectContext) var moc

@FetchRequest(entity: Group.entity(), sortDescriptors: [])
var groups: FetchedResults<Group>

@FetchRequest(entity: Item.entity(), sortDescriptors: [])
var itemsFetchedggr: FetchedResults<Item>

var group: Group

var body: some View {
    List {
        ForEach(self.group.itemsArray, id: \.self) { item in
            HStack {
                Text(item.wrappedName)
                Image(systemName: item.isFave ? "star.fill" : "star")
                    .foregroundColor(.yellow)
                    .onTapGesture {
                        item.isFave.toggle()
                        try? self.moc.save()
                }
            }
        }
    }
}
}

Upvotes: 0

Views: 65

Answers (1)

dddddeano
dddddeano

Reputation: 9

So - Calve off the Item into new struct for ItemRow - i guess this is best practice anyways, and use a for each to return the ItemRow passing in an Item.

this is pretty similar to the Landmarks Tutorial var item: Item

however we also need to make it :

@ObservedObject var item: Item.

I guess this is how swiftUI and CoreData are meant to work together, it took me ages to find a solution so i guess this will help someone in the future full code below

import SwiftUI
import CoreData

struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Group.entity(), sortDescriptors: [])
var groups: FetchedResults<Group>

var body: some View {
    NavigationView {
        VStack {
            AddDummyDataButton()
            List {
                ForEach(groups, id: \.self) { group in
                    NavigationLink(destination: GroupDetail(group: 
group)) {
                        Text(group.wrappedName)
                    }
                }.onDelete { IndexSet in
                    let deleteItem = self.groups[IndexSet.first!]
                    self.moc.delete(deleteItem)
                    try? self.moc.save()
                }
            }
        }
    }
}
}
struct GroupDetail: View {
@Environment(\.managedObjectContext) var moc

var group: Group

var body: some View {
    List {
        ForEach(self.group.itemsArray, id: \.self) { item in
            ItemRow(item: item)
        }
    }
}
}

struct ItemRow: View {
@Environment(\.managedObjectContext) var moc

@ObservedObject var item: Item

var body: some View {
    HStack {
        Text(item.wrappedName)
        Image(systemName: self.item.isFave ? "star.fill" : "star")
            .foregroundColor(.yellow)
            .onTapGesture {
                self.item.isFave.toggle()
                try? self.moc.save()
        }
    }
}
}

Upvotes: 1

Related Questions