Why my UI is not updated while CoreData is?

66 Views Asked by At

The problem I have seems to be only of UI, is this: beyond when I start the app, if in a tab I change a webApp to favorite, I should see in the list of general notifications, among others, its notifications. if I remove the webApp from the list of favorites, even the related notifications should not be shown. this seems to happen in coreData, but not in the ui. I do not have this problem with the WebApps, which update without problem.

The assumption is that even if I have saved on coreData the notifications of not currently preferred apps, I have to see only the notifications of those marked as favorites. so I want to have in the “Unread” list all the notifications that: have the variable "isRead == false" And have the variable "isPreferred" of their WebApp (a relationshipOneToOne) == to true inside the "Read" list exactly the same, but with "isRead == true" when I start the app, everything works, but if I change the state of an application later (then changing its isPreferred status), in this tab, the lists do not update, while in others it does (like the one that shows favorite WebApps).

I also tried to use a bool type @State var to update every time the list appears (via onAppear) but nothing changes.

If I print the list, inside the computed var, everything seems to work, I have the correct results, CoreData is updated without problems but the UI does not update.

import SwiftUI

struct NotificationsListView: View {
    
    @EnvironmentObject var classFromEntryPoint: ClassFromEntryPoint
    @Environment(\.managedObjectContext) private var managedObjectContext
    //-------------------------------------------------------------------
    /// FetchRequest for UNREAD notifications
    @FetchRequest(
        entity: ReceivedNotification.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \ReceivedNotification.id, ascending: true)],
        predicate: NSPredicate(format: "isRead == false AND ownerAppRelationOneToOne.isPreferred == true")
    ) var unreadNotificationsOnCD: FetchedResults<ReceivedNotification>
    
    var filteredUnreadNotificationsOnCD: [ReceivedNotification] {
        let downloadedIDs = Set(classFromEntryPoint.downloadedAppsList.map { $0.id })
        return unreadNotificationsOnCD
            .filter { downloadedIDs.contains($0.ownerAppRelationOneToOne?.id ?? "N/D") }
    }
    
    //-------------------------------------------------------------------
    /// FetchRequest for READ notifications
    @FetchRequest(
        entity: ReceivedNotification.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \ReceivedNotification.id, ascending: true)],
        predicate: NSPredicate(format: "isRead == true AND ownerAppRelationOneToOne.isPreferred == true")
    ) var readNotificationsOnCD: FetchedResults<ReceivedNotification>
    
    var filteredReadNotificationsOnCD: [ReceivedNotification] {
        let downloadedIDs = Set(classFromEntryPoint.downloadedAppsList.map { $0.id })
        return readNotificationsOnCD
            .filter { downloadedIDs.contains($0.ownerAppRelationOneToOne?.id ?? "N/D") }
    }

    var body: some View {
        NavigationView {
            
            List {
                NotificationSection(title: "Unread", notifications: Array(filteredUnreadNotificationsOnCD))
                
                NotificationSection(title: "Read", notifications: Array(filteredReadNotificationsOnCD))
            }
            .hideScrollBackgroundIfAvailableIOS16Modifier()
            .backgroundImage2_WithGeometryReader()
            
            .navigationBarTitle("Notifications")

            Text("Select a notification on left menu")
        }
        .environmentObject(classFromEntryPoint) //available in all views down

    }

    
}

struct NotificationsListView_Previews: PreviewProvider {
    static var previews: some View {
        NotificationsListView()
            .environmentObject(ClassFromEntryPoint())
    }
}



//MARK: - Accessory  view

struct NotificationSection: View {
    
    @EnvironmentObject var classFromEntryPoint: ClassFromEntryPoint
    
    var title: String
    ///Array to be used in case you wanted to give chance to delete multiple elements./
    var notifications: [ReceivedNotification]
    
    var body: some View {
        
        Section(header: Text(title)) {
            if notifications.isEmpty {
                Text("No notification")
            } else {
                ForEach(notifications, id: \.id) { notification in
                    //with a button the whole area can be tappable
                    Button {
                        classFromEntryPoint.markNotificationAsRead(notification)
                    } label: {
                        NotificationCell(notification: notification)
                    }
                    
                }
            }
        }
        
    }
}
0

There are 0 best solutions below