diff --git a/HardcoreData/ManagedObjectController.swift b/HardcoreData/ManagedObjectController.swift index d4dd9da..9a3877c 100644 --- a/HardcoreData/ManagedObjectController.swift +++ b/HardcoreData/ManagedObjectController.swift @@ -28,9 +28,7 @@ import CoreData import GCDKit -private let ManagedObjectListControllerWillChangeListNotification = "ManagedObjectListControllerWillChangeListNotification" -private let ManagedObjectListControllerDidChangeListNotification = "ManagedObjectListControllerDidChangeListNotification" - +private let ManagedObjectListControllerWillChangeObjectNotification = "ManagedObjectListControllerWillChangeObjectNotification" private let ManagedObjectListControllerDidDeleteObjectNotification = "ManagedObjectListControllerDidDeleteObjectNotification" private let ManagedObjectListControllerDidUpdateObjectNotification = "ManagedObjectListControllerDidUpdateObjectNotification" @@ -38,9 +36,7 @@ private let UserInfoKeyObject = "UserInfoKeyObject" private struct NotificationKey { - static var willChangeList: Void? - static var didChangeList: Void? - + static var willChangeObject: Void? static var didDeleteObject: Void? static var didUpdateObject: Void? } @@ -67,25 +63,24 @@ public final class ManagedObjectController: FetchedResultsCo HardcoreData.assert(GCDQueue.Main.isCurrentExecutionContext(), "Attempted to add a \(typeName(observer)) outside the main queue.") self.registerChangeNotification( - &NotificationKey.willChangeList, - name: ManagedObjectListControllerWillChangeListNotification, + &NotificationKey.willChangeObject, + name: ManagedObjectListControllerWillChangeObjectNotification, toObserver: observer, - callback: { [weak observer, weak self] (objectController) -> Void in + callback: { [weak self, weak observer] (objectController) -> Void in - if let observer = observer, let object = self?.object { + if let strongSelf = self, let object = strongSelf.object, let observer = observer { observer.managedObjectWillUpdate(objectController, object: object) } } ) - self.registerObjectNotification( &NotificationKey.didDeleteObject, name: ManagedObjectListControllerDidDeleteObjectNotification, toObserver: observer, - callback: { [weak observer] (objectController, object) -> Void in + callback: { [weak self, weak observer] (objectController, object) -> Void in - if let observer = observer { + if let strongSelf = self, let observer = observer { observer.managedObjectWasDeleted(objectController, object: object) } @@ -95,11 +90,28 @@ public final class ManagedObjectController: FetchedResultsCo &NotificationKey.didUpdateObject, name: ManagedObjectListControllerDidUpdateObjectNotification, toObserver: observer, - callback: { [weak observer] (objectController, object) -> Void in + callback: { [weak self, weak observer] (objectController, object) -> Void in - if let observer = observer { + if let strongSelf = self, let observer = observer { - observer.managedObjectWasUpdated(objectController, object: object) + let previousCommitedAttributes = strongSelf.lastCommittedAttributes + let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [NSString: NSObject] + + var changedKeys = Set() + for key in currentCommitedAttributes.keys { + + if previousCommitedAttributes[key] != currentCommitedAttributes[key] { + + changedKeys.insert(key as String) + } + } + + strongSelf.lastCommittedAttributes = currentCommitedAttributes + observer.managedObjectWasUpdated( + objectController, + object: object, + changedPersistentKeys: changedKeys + ) } } ) @@ -110,8 +122,7 @@ public final class ManagedObjectController: FetchedResultsCo HardcoreData.assert(GCDQueue.Main.isCurrentExecutionContext(), "Attempted to remove a \(typeName(observer)) outside the main queue.") let nilValue: AnyObject? = nil - setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeList, inObject: observer) - + setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeObject, inObject: observer) setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.didDeleteObject, inObject: observer) setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.didUpdateObject, inObject: observer) } @@ -145,15 +156,7 @@ public final class ManagedObjectController: FetchedResultsCo private func controllerWillChangeContent(controller: NSFetchedResultsController) { NSNotificationCenter.defaultCenter().postNotificationName( - ManagedObjectListControllerWillChangeListNotification, - object: self - ) - } - - private func controllerDidChangeContent(controller: NSFetchedResultsController) { - - NSNotificationCenter.defaultCenter().postNotificationName( - ManagedObjectListControllerDidChangeListNotification, + ManagedObjectListControllerWillChangeObjectNotification, object: self ) } @@ -171,7 +174,8 @@ public final class ManagedObjectController: FetchedResultsCo fetchRequest.resultType = .ManagedObjectResultType fetchRequest.sortDescriptors = [] - Where("SELF", isEqualTo: object).applyToFetchRequest(fetchRequest) + let originalObjectID = object.objectID + Where("SELF", isEqualTo: originalObjectID).applyToFetchRequest(fetchRequest) let fetchedResultsController = NSFetchedResultsController( fetchRequest: fetchRequest, @@ -182,6 +186,7 @@ public final class ManagedObjectController: FetchedResultsCo let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate() + self.originalObjectID = originalObjectID self.fetchedResultsController = fetchedResultsController self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate self.parentStack = dataStack @@ -196,13 +201,17 @@ public final class ManagedObjectController: FetchedResultsCo error ?? NSError(hardcoreDataErrorCode: .UnknownError), "Failed to perform fetch on <\(NSFetchedResultsController.self)>.") } + + self.lastCommittedAttributes = (self.object?.committedValuesForKeys(nil) as? [NSString: NSObject]) ?? [:] } // MARK: Private + private let originalObjectID: NSManagedObjectID private let fetchedResultsController: NSFetchedResultsController private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate + private var lastCommittedAttributes = [NSString: NSObject]() private weak var parentStack: DataStack? private func registerChangeNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (objectController: ManagedObjectController) -> Void) { @@ -257,8 +266,6 @@ private protocol FetchedResultsControllerHandler: class { func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) func controllerWillChangeContent(controller: NSFetchedResultsController) - - func controllerDidChangeContent(controller: NSFetchedResultsController) } @@ -273,11 +280,6 @@ private final class FetchedResultsControllerDelegate: NSFetchedResultsController self.handler?.controllerWillChangeContent(controller) } - @objc func controllerDidChangeContent(controller: NSFetchedResultsController) { - - self.handler?.controllerDidChangeContent(controller) - } - @objc func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath) diff --git a/HardcoreData/ManagedObjectObserver.swift b/HardcoreData/ManagedObjectObserver.swift index c89f26a..479bbdd 100644 --- a/HardcoreData/ManagedObjectObserver.swift +++ b/HardcoreData/ManagedObjectObserver.swift @@ -35,7 +35,7 @@ public protocol ManagedObjectObserver: class { func managedObjectWillUpdate(objectController: ManagedObjectController, object: EntityType) - func managedObjectWasUpdated(objectController: ManagedObjectController, object: EntityType) + func managedObjectWasUpdated(objectController: ManagedObjectController, object: EntityType, changedPersistentKeys: Set) func managedObjectWasDeleted(objectController: ManagedObjectController, object: EntityType) } diff --git a/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard b/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard index ff45e22..ddee4b5 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard +++ b/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard @@ -1,22 +1,42 @@ - + - + - + - + - + - + + + + + + + + + + + @@ -24,7 +44,7 @@ @@ -40,18 +60,58 @@ - + - + - + + + + + + + + + + + + + + + + + + + - + diff --git a/HardcoreDataDemo/HardcoreDataDemo/HardcoreDataDemo.xcdatamodeld/HardcoreDataDemo.xcdatamodel/contents b/HardcoreDataDemo/HardcoreDataDemo/HardcoreDataDemo.xcdatamodeld/HardcoreDataDemo.xcdatamodel/contents index fecdf73..6b57a6b 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/HardcoreDataDemo.xcdatamodeld/HardcoreDataDemo.xcdatamodel/contents +++ b/HardcoreDataDemo/HardcoreDataDemo/HardcoreDataDemo.xcdatamodeld/HardcoreDataDemo.xcdatamodel/contents @@ -1,5 +1,5 @@ - + diff --git a/HardcoreDataDemo/HardcoreDataDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift b/HardcoreDataDemo/HardcoreDataDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift index b23c1d7..7497c37 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift +++ b/HardcoreDataDemo/HardcoreDataDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift @@ -73,7 +73,7 @@ class ObjectObserverDemoViewController: UIViewController, ManagedObjectObserver if let palette = self.objectController?.object { - self.reloadPaletteInfo(palette) + self.reloadPaletteInfo(palette, changedKeys: nil) } } @@ -85,9 +85,9 @@ class ObjectObserverDemoViewController: UIViewController, ManagedObjectObserver // none } - func managedObjectWasUpdated(objectController: ManagedObjectController, object: Palette) { + func managedObjectWasUpdated(objectController: ManagedObjectController, object: Palette, changedPersistentKeys: Set) { - self.reloadPaletteInfo(object) + self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys) } func managedObjectWasDeleted(objectController: ManagedObjectController, object: Palette) { @@ -166,7 +166,7 @@ class ObjectObserverDemoViewController: UIViewController, ManagedObjectObserver } } - func reloadPaletteInfo(palette: Palette) { + func reloadPaletteInfo(palette: Palette, changedKeys: Set?) { self.colorNameLabel?.text = palette.colorName @@ -179,17 +179,18 @@ class ObjectObserverDemoViewController: UIViewController, ManagedObjectObserver let hue = palette.hue let saturation = palette.saturation let brightness = palette.brightness - if Int32(self.hueSlider?.value ?? 0) != hue { + + if changedKeys == nil || changedKeys?.contains("hue") == true { - self.hueSlider?.value = Float(hue) + self.hueSlider?.value = Float(palette.hue) } - if self.saturationSlider?.value != saturation { + if changedKeys == nil || changedKeys?.contains("saturation") == true { - self.saturationSlider?.value = saturation + self.saturationSlider?.value = palette.saturation } - if self.brightnessSlider?.value != brightness { + if changedKeys == nil || changedKeys?.contains("brightness") == true { - self.brightnessSlider?.value = brightness + self.brightnessSlider?.value = palette.brightness } } }