Создайте непрерывный поток информации из Core Data в ваш пользовательский интерфейс

В моей предыдущей статье RxSwift, Observables и Core Data я представил способ получить наблюдаемое непосредственно из вашего кэша Core Data. Но некоторые уже используют Apple Combine framework, поэтому я приготовил точно такое же решение для Combine.

Общая идея состоит в том, чтобы получить поток сущностей Core Data в форме издателя и отправлять новые значения каждый раз, когда эти сущности Core Data для данного FetchRequest обновляются, вставляются или удаляются.

Я не буду вдаваться в подробности того, как вы можете использовать этот поток. Более подробную информацию можно найти в моей предыдущей статье.

Нам понадобится NSFetchRequest и NSManagedObjectContext для инициализации следующего издателя:

Каждый раз, когда Core Data обновляется, CDPublisher отправляет новые значения своему подписчику.

Я рекомендую не использовать сущность Core Data напрямую, а преобразовать ее в структуру домена и использовать ее.

Вот пример объекта "Клиент":

Я бы создал следующую структуру:

struct DCustomer {
  let id: Int
  let name: String
  let phone: String
}

И сопоставьте результат CDPublisher с этим:

CDPublisher(request: Customer.fetchRequest(), context: database.viewContext)
.map { $0.map { DCustomer(id: $0.id, name: $0.name, phone $0.phone) } }

Что делать отсюда

Если вы работаете со SwiftUI, вы можете обновить свойство ViewModel Published.

Имейте в виду следующее:

  • При присвоении свойству Published значения получают в основном потоке.
  • Не используйте .assign(to: \.customers, on: self), потому что это вызывает ссылку на себя, и ваша MyViewModel никогда не будет освобождена.
  • Используйте [weak self] в закрытии .sink.
  • Существуют лучшие решения, которые могли бы заменить эту уродливую .map().recieve().sink().store(), но это тема для другой статьи.

Как всегда, удачного кодирования.