Search code examples
iosswiftcore-datamagicalrecord

Changes when record was created in today extension and updated in app are not visible in today extension


Simply I have an app, and today extension. Also I have two entities: Goal and Service.

@objc(Goal)
class Goal: NSManagedObject {

    @NSManaged var identifier: String
    @NSManaged var startDate: Date
    @NSManaged var endDate: Date

    private var services: [Service] {
    
        let predicate = NSPredicate(format: "date >= %@ && date <= %@", startDate as NSDate, endDate as NSDate)

        return Service.mr_findAll(with: predicate) as! [Service]
    }

    var duration: Int64 {
        return services.reduce(0) { $0 + $1.duration }
    }
}

When I create service related to goal in today extension and update it within an app, updated results are not visible in today extension while are displayed properly in an app. Why?

This is how I create and update record in an extension or in an extension:

MagicalRecord.save({ context in
        
    Service.createOrUpdate(withDuration: duration, date: Date(), identifier: identifier, in: context)
        
}, completion: { _, error in
        
        //do something on completion
})

Solution

  • The extension and the app are different programs that share some of the same code. So both are creating their own persistentStoreCoordinator and context(s).

    Normally in the same app you would have multiple context all attached to the same persistentStoreCoordinator and changes in one would be handled by the notifications that are sent out via notificationCenter and then merged. In this case there are two problems - 1) notificationCenter is not shared between the app and the extension so they can't communicate easily and 2) the context don't share the same persistentStoreCoordinator so you can't use 'mergeChangesFromContextDidSaveNotification` even if you did pass that information.

    I haven't tried this before, but this is what I would try:

    1. setup some way to trigger that a change occurred. There are many solutions to this.
    2. setup your managedObjectContext(s) to have a stalenessInterval of 0
    3. when there is a change you have to update your core data. You can do this by calling refreshObject:mergeChanges: on all your core data object, or do another fetch. The trick is that you have to have the context fetch from the store and the store to fetch from the file, and not hit any of the caches in the between.