Skip to content

Instantly share code, notes, and snippets.

@rpassis
Created January 13, 2019 18:07
Show Gist options
  • Save rpassis/ec07dcee226cb455ecb2bffac13fae6a to your computer and use it in GitHub Desktop.
Save rpassis/ec07dcee226cb455ecb2bffac13fae6a to your computer and use it in GitHub Desktop.
Observe changes to a CoreData context using RxSwift
import UIKit
import CoreData
import Playgrounds
import RxSwift
import RxCocoa
@objc(ProductEntity)
final class ProductEntity: NSManagedObject {
@NSManaged public var uuid: String?
@NSManaged public var title: String?
}
struct ChangeSet<T: Hashable> {
let operations: [Operation<T>]
init(userInfo: [AnyHashable: Any]) {
let operations = userInfo.reduce(into: [Operation<T>]()) { (result, next) in
let (key, value) = next
guard let specialized = value as? Set<T> else { return }
switch key.description {
case NSInsertedObjectsKey:
result.append(.inserted(specialized))
case NSUpdatedObjectsKey:
result.append(.updated(specialized))
case NSDeletedObjectsKey:
result.append(.deleted(specialized))
case NSRefreshedObjectsKey:
result.append(.refreshed(specialized))
case NSInvalidatedObjectsKey:
result.append(.invalidated(specialized))
case _:
break
}
}
self.operations = operations
}
}
enum Operation<T: Hashable> {
case inserted(Set<T>)
case deleted(Set<T>)
case updated(Set<T>)
case refreshed(Set<T>)
case invalidated(Set<T>)
}
extension Reactive where Base: NSPersistentContainer {
func changeSet(for context: NSManagedObjectContext) -> Observable<ChangeSet<NSManagedObject>> {
let notification = Notification.Name.NSManagedObjectContextObjectsDidChange
return NotificationCenter.default.rx.notification(notification)
.filter { $0.object as? NSManagedObjectContext == context }
.filter { $0.userInfo != nil }
.map { $0.userInfo! }
.map(ChangeSet<NSManagedObject>.init)
}
}
let container = NSPersistentContainer(name: "Model")
public func initializeCoreDataStack() {
container.loadPersistentStores { (description, error) in
if let loadError = error {
print("Error occured 💥! \(loadError)")
return
}
print("Success 🙆! \(description)")
}
}
initializeCoreDataStack()
let mainCx = container.viewContext
let backgroundCx = container.newBackgroundContext()
let inserted = ProductEntity(context: backgroundCx)
container.rx
.changeSet(for: backgroundCx)
.debug()
.subscribe()
backgroundCx.perform {
try? backgroundCx.save()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment