Search code examples
iosswiftswiftuicore-datawidgetkit

CoreData Widget not updating after initial run


I've been trying to update the data in my widget that is fetched from CoreData, but the Widget only refreshes when I run the project for the first time.

Neither the getTimeline, nor the getSnapshot functions are being called when I call the following function from the app when the data is saved.

WidgetCenter.shared.reloadAllTimelines()

import WidgetKit
import SwiftUI
import Intents
import CoreData

struct Provider: IntentTimelineProvider {
    
    let subjects = getData()

    
    func placeholder(in context: Context) -> SimpleEntry {
       SimpleEntry(date: Date(), subjects: [], configuration: ConfigurationIntent())
    }
    
    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        print("Snapshot called")
        let entry = SimpleEntry(date: Date(), subjects: subjects, configuration: configuration)
        completion(entry)
    }
    
    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        print("TimeLine called")
        let entry = SimpleEntry(date: Date(), subjects: subjects, configuration: configuration)
        let timeline = Timeline(entries: [entry], policy: .never)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let subjects: [Subject]
    let configuration : ConfigurationIntent
}

If it helps, I had written some similar code that worked perfectly before on another similar app. I tried uninstalling the app and downloading it again, changing the timeline policy from .never to .atEnd but it didn't work.

I don't have any user configurable options for the widget so I tried removing the ConfigurationIntent references in the code, but it doesn't work.


Solution

  • Alright so after searching through some code on GitHub I found an answer.

    import Combine
    
    class AppObserver {
        private var cancellables: Set<AnyCancellable> = []
        init(context: NSManagedObjectContext) {
            NotificationCenter.Publisher(center: .default, name: .NSManagedObjectContextObjectsDidChange, object: context)
                .sink { _ in
                    WidgetCenter.shared.reloadAllTimelines()
                }
                .store(in: &cancellables)
        }
    }
    

    I added this app observer and then passed it into the main app

        let observer = AppObserver(context: DataController.shared.container.viewContext)
    

    This seemed to solve the issue for me. Also, try deleting the data stored in CoreData and testing with new data, that was partly the problem with my code