My project has CoreData
database with 1 root context and multiple sub contexts.
I have a ViewModel
that contains an Item (NSManagedObject
). When I changes something in an Item the persistence is made in the root context and then automatically merged into all sub-contexts.
I want to replace the NSFetchedResultsController
with ReactiveSwift
Signals / Properties, to observe changes in the item object.
ViewModel:
var itemProperty: MutableProperty<Item> = MutableProperty(contextItem)
ViewController:
self.viewModel.itemProperty.signal.observeValues{ (item: Item) in
let newName = item.name
print("name: \(newName!)"
}
After I change the item's name somewhere else, the changes are propagated to the ViewModel
sub-context (the NSFetchedResultsController
gets notified), BUT the signal never pushes a new item
event.
Maybe because the NSManagedObject
reference never changes? I know I can observe changes to specific properties in an object with producer(forKeyPath: "propertyKeyPath" )
, but I don't want to observe just one specific property of the item, I want to observe ALL changes.
Is there a way to observe ANY change in all the object's properties ??
So apparently after a little research I found out ReactiveCocoa it's not so well prepared to work with Core Data. It is not possible to receive NSManagedObject updates with just ReactiveCocoa/ReactiveSwift.
One option could be updating the ItemProperty with each update from a NSFetchedResultsController and trigger a new event on the property's associated signal:
var entityProperty: MutableProperty<MyEntity>
override func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
{
entityProperty.value = anObject as! MyEntity
}
Another option could be to get a signal for updates on specific properties in my entity:
var myEntity: MyEntity
// ReactiveObjectiveC
myEntity.rac_values(forKeyPath: "name", observer: self)
// ReactiveSwift
myEntity.reactive.signal(forKeyPath: "name")