Created
January 13, 2019 18:07
-
-
Save rpassis/ec07dcee226cb455ecb2bffac13fae6a to your computer and use it in GitHub Desktop.
Observe changes to a CoreData context using RxSwift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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