From eade08d0cd83bdfb2e8c046fc50029cf2c757fff Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Thu, 7 May 2015 00:30:45 +0900 Subject: [PATCH] added demo for observing changes to a single managed object --- HardcoreData.xcodeproj/project.pbxproj | 4 + .../AsynchronousDataTransaction.swift | 4 +- HardcoreData/BaseDataTransaction.swift | 8 +- HardcoreData/DataStack+Observing.swift | 5 + HardcoreData/HardcoreData+Observing.swift | 27 ++ HardcoreData/ManagedObjectController.swift | 2 +- HardcoreData/SynchronousDataTransaction.swift | 4 +- .../project.pbxproj | 26 +- .../HardcoreDataDemo/AppDelegate.swift | 2 +- .../Base.lproj/Main.storyboard | 263 +++++++++++------- ...bjectListObserverDemoViewController.swift} | 53 +++- .../ObjectObserverDemoViewController.swift | 177 ++++++++++++ 12 files changed, 439 insertions(+), 136 deletions(-) create mode 100644 HardcoreData/HardcoreData+Observing.swift rename HardcoreDataDemo/HardcoreDataDemo/{PalettesViewController.swift => ObjectListObserverDemoViewController.swift} (77%) create mode 100644 HardcoreDataDemo/HardcoreDataDemo/ObjectObserverDemoViewController.swift diff --git a/HardcoreData.xcodeproj/project.pbxproj b/HardcoreData.xcodeproj/project.pbxproj index f69bbb3..95406e8 100644 --- a/HardcoreData.xcodeproj/project.pbxproj +++ b/HardcoreData.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ B595CAC61A9A1260009A397F /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B595CAC51A9A1260009A397F /* NSManagedObjectContext+Transaction.swift */; }; B595CAC81A9A161B009A397F /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B595CAC71A9A161B009A397F /* WeakObject.swift */; }; B5BC26DD1AF78A8800276889 /* ManagedObjectObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BC26DC1AF78A8800276889 /* ManagedObjectObserver.swift */; }; + B5BC271D1AFA500400276889 /* HardcoreData+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BC271C1AFA500400276889 /* HardcoreData+Observing.swift */; }; B5CFD36E1A0775F000B7885F /* SaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CFD36D1A0775F000B7885F /* SaveResult.swift */; }; B5CFF23E19FD1D1C00D6DFC4 /* NSManagedObjectContext+HardcoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CFF23D19FD1D1C00D6DFC4 /* NSManagedObjectContext+HardcoreData.swift */; }; B5CFF24019FD383100D6DFC4 /* BaseDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5CFF23F19FD383100D6DFC4 /* BaseDataTransaction.swift */; }; @@ -104,6 +105,7 @@ B595CAC51A9A1260009A397F /* NSManagedObjectContext+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Transaction.swift"; sourceTree = ""; }; B595CAC71A9A161B009A397F /* WeakObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeakObject.swift; sourceTree = ""; }; B5BC26DC1AF78A8800276889 /* ManagedObjectObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedObjectObserver.swift; sourceTree = ""; }; + B5BC271C1AFA500400276889 /* HardcoreData+Observing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HardcoreData+Observing.swift"; sourceTree = ""; }; B5CFD36D1A0775F000B7885F /* SaveResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveResult.swift; sourceTree = ""; }; B5CFF23D19FD1D1C00D6DFC4 /* NSManagedObjectContext+HardcoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+HardcoreData.swift"; sourceTree = ""; }; B5CFF23F19FD383100D6DFC4 /* BaseDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseDataTransaction.swift; sourceTree = ""; }; @@ -243,6 +245,7 @@ B52B68B91AAB46AD00CE7F48 /* ManagedObjectController.swift */, B5BC26DC1AF78A8800276889 /* ManagedObjectObserver.swift */, B52B68BD1AAB484C00CE7F48 /* DataStack+Observing.swift */, + B5BC271C1AFA500400276889 /* HardcoreData+Observing.swift */, ); name = Observing; sourceTree = ""; @@ -532,6 +535,7 @@ B5E209E01A0726460089C9D4 /* NSManagedObject+Transaction.swift in Sources */, B582DF821A98B0E7003F09C6 /* HardcoreData+Querying.swift in Sources */, B5D19BFB1AA14063001D1A99 /* AsynchronousDataTransaction.swift in Sources */, + B5BC271D1AFA500400276889 /* HardcoreData+Observing.swift in Sources */, B595CAC81A9A161B009A397F /* WeakObject.swift in Sources */, B5D1E22A19FA9E63003B2874 /* PersistentStoreResult.swift in Sources */, B5398AA21AA8938D00B66388 /* DetachedDataTransaction.swift in Sources */, diff --git a/HardcoreData/AsynchronousDataTransaction.swift b/HardcoreData/AsynchronousDataTransaction.swift index 23b3f3e..615010a 100644 --- a/HardcoreData/AsynchronousDataTransaction.swift +++ b/HardcoreData/AsynchronousDataTransaction.swift @@ -108,7 +108,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { :param: object the NSManagedObject type to be edited :returns: an editable proxy for the specified NSManagedObject. */ - public override func fetch(object: T) -> T? { + public override func fetch(object: T?) -> T? { HardcoreData.assert(!self.isCommitted, "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self)).") @@ -120,7 +120,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { :param: object the NSManagedObject type to be deleted */ - public override func delete(object: NSManagedObject) { + public override func delete(object: NSManagedObject?) { HardcoreData.assert(!self.isCommitted, "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self)).") diff --git a/HardcoreData/BaseDataTransaction.swift b/HardcoreData/BaseDataTransaction.swift index fc09afa..c06ca45 100644 --- a/HardcoreData/BaseDataTransaction.swift +++ b/HardcoreData/BaseDataTransaction.swift @@ -61,11 +61,11 @@ public /*abstract*/ class BaseDataTransaction { :param: object the NSManagedObject type to be edited :returns: an editable proxy for the specified NSManagedObject. */ - public func fetch(object: T) -> T? { + public func fetch(object: T?) -> T? { HardcoreData.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to update an entity of type \(typeName(object)) outside its designated queue.") - return object.inContext(self.context) + return object?.inContext(self.context) } /** @@ -73,11 +73,11 @@ public /*abstract*/ class BaseDataTransaction { :param: object the NSManagedObject type to be deleted */ - public func delete(object: NSManagedObject) { + public func delete(object: NSManagedObject?) { HardcoreData.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to delete an entity of type \(typeName(object)) outside its designated queue.") - object.inContext(self.context)?.deleteFromContext() + object?.inContext(self.context)?.deleteFromContext() } // MARK: Saving changes diff --git a/HardcoreData/DataStack+Observing.swift b/HardcoreData/DataStack+Observing.swift index d2db2bf..592a162 100644 --- a/HardcoreData/DataStack+Observing.swift +++ b/HardcoreData/DataStack+Observing.swift @@ -46,6 +46,11 @@ public extension DataStack { public func observeObjectList(from: From, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ManagedObjectListController { + return self.observeObjectList(from, groupBy, queryClauses) + } + + public func observeObjectList(from: From, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ManagedObjectListController { + HardcoreData.assert(GCDQueue.Main.isCurrentExecutionContext(), "Attempted to observe objects from \(typeName(self)) outside the main queue.") // TODO: sectionNameKeyPath and cacheResults diff --git a/HardcoreData/HardcoreData+Observing.swift b/HardcoreData/HardcoreData+Observing.swift new file mode 100644 index 0000000..df109b6 --- /dev/null +++ b/HardcoreData/HardcoreData+Observing.swift @@ -0,0 +1,27 @@ +// +// HardcoreData+Observing.swift +// HardcoreData +// +// Created by John Rommel Estropia on 2015/05/06. +// Copyright (c) 2015 John Rommel Estropia. All rights reserved. +// + +import Foundation + + +// MARK: - HardcoreData + +public extension HardcoreData { + + // MARK: Public + + public static func observeObject(object: T) -> ManagedObjectController { + + return self.defaultStack.observeObject(object) + } + + public static func observeObjectList(from: From, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ManagedObjectListController { + + return self.defaultStack.observeObjectList(from, groupBy, queryClauses) + } +} \ No newline at end of file diff --git a/HardcoreData/ManagedObjectController.swift b/HardcoreData/ManagedObjectController.swift index 8aa0940..d4dd9da 100644 --- a/HardcoreData/ManagedObjectController.swift +++ b/HardcoreData/ManagedObjectController.swift @@ -169,9 +169,9 @@ public final class ManagedObjectController: FetchedResultsCo fetchRequest.entity = context.entityDescriptionForEntityClass(T.self) fetchRequest.fetchLimit = 1 fetchRequest.resultType = .ManagedObjectResultType + fetchRequest.sortDescriptors = [] Where("SELF", isEqualTo: object).applyToFetchRequest(fetchRequest) - SortedBy(.Ascending("objectID")).applyToFetchRequest(fetchRequest) let fetchedResultsController = NSFetchedResultsController( fetchRequest: fetchRequest, diff --git a/HardcoreData/SynchronousDataTransaction.swift b/HardcoreData/SynchronousDataTransaction.swift index a080b4c..2105c8d 100644 --- a/HardcoreData/SynchronousDataTransaction.swift +++ b/HardcoreData/SynchronousDataTransaction.swift @@ -66,7 +66,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction { :param: object the NSManagedObject type to be edited :returns: an editable proxy for the specified NSManagedObject. */ - public override func fetch(object: T) -> T? { + public override func fetch(object: T?) -> T? { HardcoreData.assert(!self.isCommitted, "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self)).") @@ -78,7 +78,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction { :param: object the NSManagedObject type to be deleted */ - public override func delete(object: NSManagedObject) { + public override func delete(object: NSManagedObject?) { HardcoreData.assert(!self.isCommitted, "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self)).") diff --git a/HardcoreDataDemo/HardcoreDataDemo.xcodeproj/project.pbxproj b/HardcoreDataDemo/HardcoreDataDemo.xcodeproj/project.pbxproj index 111f166..1a7f25d 100644 --- a/HardcoreDataDemo/HardcoreDataDemo.xcodeproj/project.pbxproj +++ b/HardcoreDataDemo/HardcoreDataDemo.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */; }; B54AAD521AF4D26E00848AE0 /* HardcoreDataDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD501AF4D26E00848AE0 /* HardcoreDataDemo.xcdatamodeld */; }; - B54AAD541AF4D26E00848AE0 /* PalettesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD531AF4D26E00848AE0 /* PalettesViewController.swift */; }; + B54AAD541AF4D26E00848AE0 /* ObjectListObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD531AF4D26E00848AE0 /* ObjectListObserverDemoViewController.swift */; }; B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; }; B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; }; B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; }; @@ -18,6 +18,7 @@ B583A9211AF5F542001F76AF /* HardcoreData.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B583A91B1AF5F4F4001F76AF /* HardcoreData.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B5BC26E41AF8F67900276889 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BC26E31AF8F67900276889 /* PaletteTableViewCell.swift */; }; B5BC26E81AF8FD9600276889 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BC26E71AF8FD9600276889 /* Palette.swift */; }; + B5BC271B1AFA4E6900276889 /* ObjectObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BC271A1AFA4E6900276889 /* ObjectObserverDemoViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -77,7 +78,7 @@ B54AAD4D1AF4D26E00848AE0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; B54AAD511AF4D26E00848AE0 /* HardcoreDataDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = HardcoreDataDemo.xcdatamodel; sourceTree = ""; }; - B54AAD531AF4D26E00848AE0 /* PalettesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PalettesViewController.swift; sourceTree = ""; }; + B54AAD531AF4D26E00848AE0 /* ObjectListObserverDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectListObserverDemoViewController.swift; sourceTree = ""; }; B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; @@ -88,6 +89,7 @@ B583A9251AF5F547001F76AF /* GCDKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = GCDKit.framework; path = "/Users/johnestropia/Library/Developer/Xcode/DerivedData/HardcoreDataDemo-ftknhsqfpsthfogvisxisgpbbhsj/Build/Products/Debug-iphoneos/GCDKit.framework"; sourceTree = ""; }; B5BC26E31AF8F67900276889 /* PaletteTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaletteTableViewCell.swift; sourceTree = ""; }; B5BC26E71AF8FD9600276889 /* Palette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palette.swift; sourceTree = ""; }; + B5BC271A1AFA4E6900276889 /* ObjectObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverDemoViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -133,7 +135,8 @@ isa = PBXGroup; children = ( B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */, - B5BC26E51AF8F67D00276889 /* DataSources */, + B5BC26E51AF8F67D00276889 /* Cells */, + B5BC27191AFA4E0500276889 /* Demo */, B5BC26E61AF8F68200276889 /* Entities */, B54AAD571AF4D26E00848AE0 /* Main.storyboard */, B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */, @@ -178,13 +181,12 @@ name = Products; sourceTree = ""; }; - B5BC26E51AF8F67D00276889 /* DataSources */ = { + B5BC26E51AF8F67D00276889 /* Cells */ = { isa = PBXGroup; children = ( - B54AAD531AF4D26E00848AE0 /* PalettesViewController.swift */, B5BC26E31AF8F67900276889 /* PaletteTableViewCell.swift */, ); - name = DataSources; + name = Cells; sourceTree = ""; }; B5BC26E61AF8F68200276889 /* Entities */ = { @@ -195,6 +197,15 @@ name = Entities; sourceTree = ""; }; + B5BC27191AFA4E0500276889 /* Demo */ = { + isa = PBXGroup; + children = ( + B54AAD531AF4D26E00848AE0 /* ObjectListObserverDemoViewController.swift */, + B5BC271A1AFA4E6900276889 /* ObjectObserverDemoViewController.swift */, + ); + name = Demo; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -323,9 +334,10 @@ files = ( B54AAD521AF4D26E00848AE0 /* HardcoreDataDemo.xcdatamodeld in Sources */, B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */, + B5BC271B1AFA4E6900276889 /* ObjectObserverDemoViewController.swift in Sources */, B5BC26E41AF8F67900276889 /* PaletteTableViewCell.swift in Sources */, B5BC26E81AF8FD9600276889 /* Palette.swift in Sources */, - B54AAD541AF4D26E00848AE0 /* PalettesViewController.swift in Sources */, + B54AAD541AF4D26E00848AE0 /* ObjectListObserverDemoViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/HardcoreDataDemo/HardcoreDataDemo/AppDelegate.swift b/HardcoreDataDemo/HardcoreDataDemo/AppDelegate.swift index 4b53ebd..355aea4 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/AppDelegate.swift +++ b/HardcoreDataDemo/HardcoreDataDemo/AppDelegate.swift @@ -13,7 +13,7 @@ import HardcoreData let paletteList: ManagedObjectListController = { HardcoreData.defaultStack.addSQLiteStore() - return HardcoreData.defaultStack.observeObjectList( + return HardcoreData.observeObjectList( From(Palette), GroupBy("colorName"), SortedBy(.Ascending("hue"), .Ascending("dateAdded")) diff --git a/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard b/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard index fc47c7f..959cdd6 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard +++ b/HardcoreDataDemo/HardcoreDataDemo/Base.lproj/Main.storyboard @@ -10,14 +10,14 @@ - + - + @@ -28,7 +28,7 @@ - - + @@ -51,95 +51,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -162,7 +77,139 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -175,13 +222,13 @@ - + - + @@ -199,7 +246,9 @@ - + + + @@ -208,7 +257,7 @@ - + @@ -316,12 +365,12 @@ - + - + - + @@ -364,17 +413,18 @@ + - + - + - + @@ -417,7 +467,7 @@ - + @@ -426,7 +476,8 @@ - + + diff --git a/HardcoreDataDemo/HardcoreDataDemo/PalettesViewController.swift b/HardcoreDataDemo/HardcoreDataDemo/ObjectListObserverDemoViewController.swift similarity index 77% rename from HardcoreDataDemo/HardcoreDataDemo/PalettesViewController.swift rename to HardcoreDataDemo/HardcoreDataDemo/ObjectListObserverDemoViewController.swift index 9ffb6d7..0e28857 100644 --- a/HardcoreDataDemo/HardcoreDataDemo/PalettesViewController.swift +++ b/HardcoreDataDemo/HardcoreDataDemo/ObjectListObserverDemoViewController.swift @@ -1,5 +1,5 @@ // -// PalettesViewController.swift +// ObjectListObserverDemoViewController.swift // HardcoreDataDemo // // Created by John Rommel Estropia on 2015/05/02. @@ -10,9 +10,9 @@ import UIKit import HardcoreData -// MARK: - PalettesViewController +// MARK: - ObjectListObserverDemoViewController -class PalettesViewController: UITableViewController, ManagedObjectListSectionObserver { +class ObjectListObserverDemoViewController: UITableViewController, ManagedObjectListSectionObserver { // MARK: NSObject @@ -30,10 +30,32 @@ class PalettesViewController: UITableViewController, ManagedObjectListSectionObs self.navigationItem.leftBarButtonItems = [ self.editButtonItem(), - UIBarButtonItem(barButtonSystemItem: .Trash, target: self, action: "resetBarButtonItemTouched:") + UIBarButtonItem( + barButtonSystemItem: .Trash, + target: self, + action: "resetBarButtonItemTouched:" + ) ] - self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "addBarButtonItemTouched:") + self.navigationItem.rightBarButtonItem = UIBarButtonItem( + barButtonSystemItem: .Add, + target: self, + action: "addBarButtonItemTouched:" + ) + } + + override func viewWillAppear(animated: Bool) { + + super.viewWillAppear(animated) + paletteList.addObserver(self) + self.tableView.reloadData() + } + + override func viewDidDisappear(animated: Bool) { + + super.viewDidDisappear(animated) + + paletteList.removeObserver(self) } @@ -110,9 +132,11 @@ class PalettesViewController: UITableViewController, ManagedObjectListSectionObs func managedObjectList(listController: ManagedObjectListController, didUpdateObject object: Palette, atIndexPath indexPath: NSIndexPath) { - let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! PaletteTableViewCell - let palette = paletteList[indexPath] - cell.setHue(palette.hue, saturation: palette.saturation, brightness: palette.brightness) + if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? PaletteTableViewCell { + + let palette = paletteList[indexPath] + cell.setHue(palette.hue, saturation: palette.saturation, brightness: palette.brightness) + } } func managedObjectList(listController: ManagedObjectListController, didMoveObject object: Palette, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { @@ -149,11 +173,14 @@ class PalettesViewController: UITableViewController, ManagedObjectListSectionObs HardcoreData.beginAsynchronous { (transaction) -> Void in - let palette = transaction.create(Palette) - palette.hue = Int32(arc4random_uniform(360)) - palette.saturation = 1.0 - palette.brightness = 0.5 - palette.dateAdded = NSDate() + for _ in 0 ... 2 { + + let palette = transaction.create(Palette) + palette.hue = Int32(arc4random_uniform(360)) + palette.saturation = 1.0 + palette.brightness = 0.5 + palette.dateAdded = NSDate() + } transaction.commit { (result) -> Void in } } diff --git a/HardcoreDataDemo/HardcoreDataDemo/ObjectObserverDemoViewController.swift b/HardcoreDataDemo/HardcoreDataDemo/ObjectObserverDemoViewController.swift new file mode 100644 index 0000000..d33f8da --- /dev/null +++ b/HardcoreDataDemo/HardcoreDataDemo/ObjectObserverDemoViewController.swift @@ -0,0 +1,177 @@ +// +// ObjectObserverDemoViewController.swift +// HardcoreDataDemo +// +// Created by John Rommel Estropia on 2015/05/06. +// Copyright (c) 2015 John Rommel Estropia. All rights reserved. +// + +import UIKit +import HardcoreData + + +// MARK: - ObjectObserverDemoViewController + +class ObjectObserverDemoViewController: UIViewController, ManagedObjectObserver { + + // MARK: NSObject + + deinit { + + self.objectController.removeObserver(self) + } + + + // MARK: UIViewController + + required init(coder aDecoder: NSCoder) { + + if let palette = HardcoreData.fetchOne(From(Palette), SortedBy(.Ascending("hue"))) { + + self.objectController = HardcoreData.observeObject(palette) + } + else { + + HardcoreData.beginSynchronous { (transaction) -> Void in + + let palette = transaction.create(Palette) + palette.hue = Int32(arc4random_uniform(360)) + palette.saturation = 1.0 + palette.brightness = 0.5 + palette.dateAdded = NSDate() + + transaction.commitAndWait() + } + + let palette = HardcoreData.fetchOne(From(Palette), SortedBy(.Ascending("hue")))! + self.objectController = HardcoreData.observeObject(palette) + } + + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + + super.viewDidLoad() + self.objectController.addObserver(self) + + if let palette = self.objectController.object { + + self.reloadPaletteInfo(palette) + self.hueSlider?.value = Float(palette.hue) + self.saturationSlider?.value = palette.saturation + self.brightnessSlider?.value = palette.brightness + } + } + + + // MARK: ManagedObjectObserver + + func managedObjectWillUpdate(objectController: ManagedObjectController, object: Palette) { + + } + + func managedObjectWasUpdated(objectController: ManagedObjectController, object: Palette) { + + self.reloadPaletteInfo(object) + } + + func managedObjectWasDeleted(objectController: ManagedObjectController, object: Palette) { + + self.colorNameLabel?.alpha = 0.3 + self.colorView?.alpha = 0.3 + self.dateLabel?.text = "Deleted" + self.dateLabel?.textColor = UIColor.redColor() + + self.hueSlider?.enabled = false + self.saturationSlider?.enabled = false + self.brightnessSlider?.enabled = false + } + + + // MARK: Private + + let objectController: ManagedObjectController + + @IBOutlet weak var colorNameLabel: UILabel? + @IBOutlet weak var colorView: UIView? + @IBOutlet weak var hsbLabel: UILabel? + @IBOutlet weak var dateLabel: UILabel? + @IBOutlet weak var hueSlider: UISlider? + @IBOutlet weak var saturationSlider: UISlider? + @IBOutlet weak var brightnessSlider: UISlider? + + @IBAction dynamic func hueSliderValueDidChange(sender: AnyObject?) { + + let hue = self.hueSlider?.value ?? 0 + HardcoreData.beginAsynchronous { [weak self] (transaction) -> Void in + + if let palette = transaction.fetch(self?.objectController.object) { + + palette.hue = Int32(hue) + palette.dateAdded = NSDate() + transaction.commit { (result) -> Void in } + } + } + } + + @IBAction dynamic func saturationSliderValueDidChange(sender: AnyObject?) { + + let saturation = self.saturationSlider?.value ?? 0 + HardcoreData.beginAsynchronous { [weak self] (transaction) -> Void in + + if let palette = transaction.fetch(self?.objectController.object) { + + palette.saturation = saturation + palette.dateAdded = NSDate() + transaction.commit { (result) -> Void in } + } + } + } + + @IBAction dynamic func brightnessSliderValueDidChange(sender: AnyObject?) { + + let brightness = self.brightnessSlider?.value ?? 0 + HardcoreData.beginAsynchronous { [weak self] (transaction) -> Void in + + if let palette = transaction.fetch(self?.objectController.object) { + + palette.brightness = brightness + palette.dateAdded = NSDate() + transaction.commit { (result) -> Void in } + } + } + } + + @IBAction dynamic func deleteBarButtonTapped(sender: AnyObject?) { + + HardcoreData.beginAsynchronous { [weak self] (transaction) -> Void in + + transaction.delete(self?.objectController.object) + transaction.commit { (result) -> Void in } + } + + (sender as? UIBarButtonItem)?.enabled = false + } + + func reloadPaletteInfo(palette: Palette) { + + let color = UIColor( + hue: CGFloat(palette.hue) / 360.0, + saturation: CGFloat(palette.saturation), + brightness: CGFloat(palette.brightness), + alpha: 1.0 + ) + self.colorNameLabel?.textColor = color + self.colorNameLabel?.text = palette.colorName + self.colorView?.backgroundColor = color + self.hsbLabel?.text = "H: \(palette.hue)˚, S: \(round(palette.saturation * 100.0))%, B: \(round(palette.brightness * 100.0))%" + + let dateString = NSDateFormatter.localizedStringFromDate( + palette.dateAdded, + dateStyle: .ShortStyle, + timeStyle: .LongStyle + ) + self.dateLabel?.text = "Updated: \(dateString)" + } +}