Reputation: 1457
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 ??
Upvotes: 3
Views: 796
Reputation: 1457
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")
Upvotes: 0
Reputation: 5020
You could observe NSManagedObjectContextObjectsDidChange
. This may be somewhat overkill, because it sends a notification when any change occurs to any objects(s). But I've used it without any noticeable performance hit. Here is the Apple documentation.
The main drawback of NSManagedObjectContextObjectsDidChange
is that it does not give you the changed keys or values. If you need that, realize that creating observers on all properties may not be as onerous as you think. It can be done in a single loop, iterating over NSEntityDescription.properties
or one of the other four similar properties listed at the bottom of its documentation.
Upvotes: 0