diff --git a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents index 40c216e..7df0666 100644 --- a/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/CoreStoreDemo.xcdatamodeld/CoreStoreDemo.xcdatamodel/contents @@ -1,36 +1,25 @@ - - - - - - - - + - - + + - - + + - + - - - - diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift index 27f5fab..de745c9 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift @@ -10,7 +10,7 @@ import UIKit import CoreStore -private struct Static { +struct ColorsDemo { enum Filter: String { @@ -33,8 +33,8 @@ private struct Static { switch self { case .all: return Where(true) - case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9) - case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4) + case .light: return Palette.where({ $0.brightness >= 0.9 }) + case .dark: return Palette.where({ $0.brightness <= 0.4 }) } } } @@ -45,25 +45,38 @@ private struct Static { self.palettes.refetch( self.filter.whereClause(), - OrderBy(.ascending(#keyPath(Palette.hue))) + Palette.orderBy(ascending: { $0.hue }) ) } } + static let stack: DataStack = { + + return DataStack( + CoreStoreSchema( + modelVersion: "ColorsDemo", + entities: [ + Entity("Palette"), + ], + versionLock: [ + "Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f] + ] + ) + ) + }() + static let palettes: ListMonitor = { - try! CoreStore.addStorageAndWait( + try! ColorsDemo.stack.addStorageAndWait( SQLiteStore( fileName: "ColorsDemo.sqlite", - configuration: "ObservingDemo", localStorageOptions: .recreateStoreOnModelMismatch ) ) - - return CoreStore.monitorSectionedList( + return ColorsDemo.stack.monitorSectionedList( From(), - SectionBy(#keyPath(Palette.colorName)), - OrderBy(.ascending(#keyPath(Palette.hue))) + SectionBy(Palette.keyPath({ $0.colorName })), + Palette.orderBy(ascending: { $0.hue }) ) }() } @@ -77,7 +90,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver deinit { - Static.palettes.removeObserver(self) + ColorsDemo.palettes.removeObserver(self) } @@ -98,7 +111,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver ] let filterBarButton = UIBarButtonItem( - title: Static.filter.rawValue, + title: ColorsDemo.filter.rawValue, style: .plain, target: self, action: #selector(self.filterBarButtonItemTouched(_:)) @@ -113,9 +126,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver ] self.filterBarButton = filterBarButton - Static.palettes.addObserver(self) + ColorsDemo.palettes.addObserver(self) - self.setTable(enabled: !Static.palettes.isPendingRefetch) + self.setTable(enabled: !ColorsDemo.palettes.isPendingRefetch) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -137,19 +150,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver override func numberOfSections(in tableView: UITableView) -> Int { - return Static.palettes.numberOfSections() + return ColorsDemo.palettes.numberOfSections() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return Static.palettes.numberOfObjectsInSection(section) + return ColorsDemo.palettes.numberOfObjectsInSection(section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell - let palette = Static.palettes[indexPath] + let palette = ColorsDemo.palettes[indexPath] cell.colorView?.backgroundColor = palette.color cell.label?.text = palette.colorText @@ -165,7 +178,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver self.performSegue( withIdentifier: "ObjectObserverDemoViewController", - sender: Static.palettes[indexPath] + sender: ColorsDemo.palettes[indexPath] ) } @@ -174,8 +187,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver switch editingStyle { case .delete: - let palette = Static.palettes[indexPath] - CoreStore.perform( + let palette = ColorsDemo.palettes[indexPath] + ColorsDemo.stack.perform( asynchronous: { (transaction) in transaction.delete(palette) @@ -190,7 +203,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - return Static.palettes.sectionInfoAtIndex(section).name + return ColorsDemo.palettes.sectionInfoAtIndex(section).name } @@ -213,7 +226,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver func listMonitorDidRefetch(_ monitor: ListMonitor) { - self.filterBarButton?.title = Static.filter.rawValue + self.filterBarButton?.title = ColorsDemo.filter.rawValue self.tableView.reloadData() self.setTable(enabled: true) } @@ -235,7 +248,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell { - let palette = Static.palettes[indexPath] + let palette = ColorsDemo.palettes[indexPath] cell.colorView?.backgroundColor = palette.color cell.label?.text = palette.colorText } @@ -268,7 +281,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver @IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) { - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { (transaction) in transaction.deleteAll(From()) @@ -279,16 +292,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver @IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) { - Static.filter = Static.filter.next() + ColorsDemo.filter = ColorsDemo.filter.next() } @IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) { - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { (transaction) in let palette = transaction.create(Into()) - palette.setInitialValues() + palette.setInitialValues(in: transaction) }, completion: { _ in } ) diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift index ce95fe4..d50ca20 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift @@ -29,7 +29,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { if let palette = newValue { - self.monitor = CoreStore.monitorObject(palette) + self.monitor = ColorsDemo.stack.monitorObject(palette) } else { @@ -50,22 +50,22 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { required init?(coder aDecoder: NSCoder) { - if let palette = CoreStore.fetchOne(From(), OrderBy(.ascending(#keyPath(Palette.hue)))) { + if let palette = ColorsDemo.stack.fetchOne(From(), Palette.orderBy(ascending: { $0.hue })) { - self.monitor = CoreStore.monitorObject(palette) + self.monitor = ColorsDemo.stack.monitorObject(palette) } else { - _ = try? CoreStore.perform( + _ = try? ColorsDemo.stack.perform( synchronous: { (transaction) in - let palette = transaction.create(Into(Palette.self)) - palette.setInitialValues() + let palette = transaction.create(Into()) + palette.setInitialValues(in: transaction) } ) - let palette = CoreStore.fetchOne(From(), OrderBy(.ascending(#keyPath(Palette.hue))))! - self.monitor = CoreStore.monitorObject(palette) + let palette = ColorsDemo.stack.fetchOne(From(), Palette.orderBy(ascending: { $0.hue }))! + self.monitor = ColorsDemo.stack.monitorObject(palette) } super.init(coder: aDecoder) @@ -121,12 +121,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { @IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) { let hue = self.hueSlider?.value ?? 0 - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { [weak self] (transaction) in if let palette = transaction.edit(self?.monitor?.object) { - palette.hue = Int32(hue) + palette.hue .= Int(hue) } }, completion: { _ in } @@ -136,12 +136,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { @IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) { let saturation = self.saturationSlider?.value ?? 0 - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { [weak self] (transaction) in if let palette = transaction.edit(self?.monitor?.object) { - palette.saturation = saturation + palette.saturation .= saturation } }, completion: { _ in } @@ -151,12 +151,12 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { @IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) { let brightness = self.brightnessSlider?.value ?? 0 - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { [weak self] (transaction) in if let palette = transaction.edit(self?.monitor?.object) { - palette.brightness = brightness + palette.brightness .= brightness } }, completion: { _ in } @@ -165,7 +165,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { @IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) { - CoreStore.perform( + ColorsDemo.stack.perform( asynchronous: { [weak self] (transaction) in transaction.delete(self?.monitor?.object) @@ -176,7 +176,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { func reloadPaletteInfo(_ palette: Palette, changedKeys: Set?) { - self.colorNameLabel?.text = palette.colorName + self.colorNameLabel?.text = palette.colorName.value let color = palette.color self.colorNameLabel?.textColor = color @@ -184,17 +184,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { self.hsbLabel?.text = palette.colorText - if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.hue)) == true { + if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.hue }) == true { - self.hueSlider?.value = Float(palette.hue) + self.hueSlider?.value = Float(palette.hue.value) } - if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.saturation)) == true { + if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.saturation }) == true { - self.saturationSlider?.value = palette.saturation + self.saturationSlider?.value = palette.saturation.value } - if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.brightness)) == true { + if changedKeys == nil || changedKeys?.contains(Palette.keyPath{ $0.brightness }) == true { - self.brightnessSlider?.value = palette.brightness + self.brightnessSlider?.value = palette.brightness.value } } } diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift index fffc643..07fd502 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift @@ -14,64 +14,65 @@ import CoreStore // MARK: - Palette -class Palette: NSManagedObject { - - @NSManaged var hue: Int32 - @NSManaged var saturation: Float - @NSManaged var brightness: Float +final class Palette: CoreStoreObject { - @objc dynamic var colorName: String { + let hue = Value.Required("hue") + let saturation = Value.Required("saturation") + let brightness = Value.Required("brightness") + + let colorName = Value.Optional( + "colorName", + isTransient: true, + customGetter: Palette.getCachedColorName + ) + + private static func getCachedColorName(_ instance: Palette, _ getValue: () -> String?) -> String? { - get { + if let colorName = getValue() { - let KVCKey = #keyPath(Palette.colorName) - if let colorName = self.getValue(forKvcKey: KVCKey) as? String { - - return colorName - } - - let colorName: String - switch self.hue % 360 { - - case 0 ..< 20: colorName = "Lower Reds" - case 20 ..< 57: colorName = "Oranges and Browns" - case 57 ..< 90: colorName = "Yellow-Greens" - case 90 ..< 159: colorName = "Greens" - case 159 ..< 197: colorName = "Blue-Greens" - case 197 ..< 241: colorName = "Blues" - case 241 ..< 297: colorName = "Violets" - case 297 ..< 331: colorName = "Magentas" - default: colorName = "Upper Reds" - } - - self.setPrimitiveValue(colorName, forKey: KVCKey) return colorName } - set { + + let colorName: String + switch instance.hue.value % 360 { - self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName)) + case 0 ..< 20: colorName = "Lower Reds" + case 20 ..< 57: colorName = "Oranges and Browns" + case 57 ..< 90: colorName = "Yellow-Greens" + case 90 ..< 159: colorName = "Greens" + case 159 ..< 197: colorName = "Blue-Greens" + case 197 ..< 241: colorName = "Blues" + case 241 ..< 297: colorName = "Violets" + case 297 ..< 331: colorName = "Magentas" + default: colorName = "Upper Reds" } + + instance.colorName.primitiveValue = colorName + return colorName } +} + +extension Palette { var color: UIColor { return UIColor( - hue: CGFloat(self.hue) / 360.0, - saturation: CGFloat(self.saturation), - brightness: CGFloat(self.brightness), + hue: CGFloat(self.hue.value) / 360.0, + saturation: CGFloat(self.saturation.value), + brightness: CGFloat(self.brightness.value), alpha: 1.0 ) } var colorText: String { - return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%" + return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%" } - func setInitialValues() { + func setInitialValues(in transaction: BaseDataTransaction) { - self.hue = Int32(arc4random_uniform(360)) - self.saturation = 1.0 - self.brightness = Float(arc4random_uniform(70) + 30) / 100.0 + self.hue .= Int(arc4random_uniform(360)) + self.saturation .= Float(1.0) + self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0 } }