ReactiveSwift: наблюдайте за изменениями управляемого объекта с помощью MutableProperty

В моем проекте CoreData база данных с 1 корневым контекстом и несколькими подконтекстами. У меня есть ViewModel, содержащий элемент (NSManagedObject). Когда я что-то меняю в элементе, постоянство создается в корневом контексте, а затем автоматически объединяется со всеми подконтекстами.

Я хочу заменить NSFetchedResultsController на ReactiveSwift Сигналы / Свойства, чтобы наблюдать изменения в объекте элемента.

ViewModel:

var itemProperty: MutableProperty<Item> = MutableProperty(contextItem)

ViewController:

self.viewModel.itemProperty.signal.observeValues{ (item: Item) in
     let newName = item.name
     print("name: \(newName!)" 
 }

После того, как я изменил имя элемента в другом месте, изменения распространяются на подконтекст ViewModel (NSFetchedResultsController получает уведомление), НО сигнал никогда не подталкивает новое событие item.

Может быть, потому что ссылка NSManagedObject никогда не меняется? Я знаю, что могу наблюдать за изменениями определенных свойств объекта с помощью producer(forKeyPath: "propertyKeyPath" ), но я не хочу наблюдать только одно конкретное свойство элемента, я хочу наблюдать ВСЕ изменения.

Есть ли способ наблюдать ЛЮБОЕ изменение всех свойств объекта ??


person 6rod9    schedule 29.04.2019    source источник


Ответы (2)


Вы могли наблюдать NSManagedObjectContextObjectsDidChange. Это может быть несколько излишним, поскольку он отправляет уведомление, когда любое изменение происходит с любыми объектами. Но я использовал его без заметного снижения производительности. Вот документация Apple.

Главный недостаток NSManagedObjectContextObjectsDidChange в том, что он не дает вам измененных ключей или значений. Если вам это нужно, поймите, что создание наблюдателей для всех свойств может быть не так обременительно, как вы думаете. Это можно сделать в одном цикле, повторяя NSEntityDescription.properties или одно из четырех других аналогичных свойств, перечисленных в нижней части его документация.

person Jerry Krinock    schedule 29.04.2019
comment
Да! Я знаю, что могу использовать NSManagedObejctContext, но я хотел полностью отслеживать изменения с помощью ReactiveSwift. Потому что, если я использую NSManagedObjectContextObjectsDidChange, я бы просто использовал сигналы ReactiveSwift для замены шаблона делегата. - person 6rod9; 02.05.2019

Итак, очевидно, после небольшого исследования я обнаружил, что ReactiveCocoa не так хорошо подготовлен для работы с Core Data. Невозможно получать обновления NSManagedObject только с помощью ReactiveCocoa / ReactiveSwift.

Одним из вариантов может быть обновление ItemProperty с каждым обновлением из NSFetchedResultsController и запуск нового события для сигнала, связанного со свойством:

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
}

Другой вариант - получить сигнал об обновлениях определенных свойств в моей сущности:

var myEntity: MyEntity

// ReactiveObjectiveC
myEntity.rac_values(forKeyPath: "name", observer: self)

// ReactiveSwift
myEntity.reactive.signal(forKeyPath: "name")
person 6rod9    schedule 17.06.2019