Implement dynamic initializers for Field properties (fixes #382)

This commit is contained in:
John Estropia
2020-05-23 12:07:16 +09:00
parent a7568eebdb
commit 56d0ea46ea
15 changed files with 455 additions and 142 deletions

View File

@@ -146,8 +146,7 @@ final class CollectionViewDemoViewController: UICollectionViewController {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
@@ -159,8 +158,8 @@ final class CollectionViewDemoViewController: UICollectionViewController {
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue()
palette.colorName .= nil
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }

View File

@@ -35,8 +35,8 @@ struct ColorsDemo {
switch self {
case .all: return .init()
case .light: return (\Palette.brightness >= 0.9)
case .dark: return (\Palette.brightness <= 0.4)
case .light: return (\Palette.$brightness >= 0.9)
case .dark: return (\Palette.$brightness <= 0.4)
}
}
}
@@ -47,9 +47,9 @@ struct ColorsDemo {
try! self.palettes.refetch(
From<Palette>()
.sectionBy(\.colorName)
.sectionBy(\.$colorName)
.where(self.filter.whereClause())
.orderBy(.ascending(\.hue))
.orderBy(.ascending(\.$hue))
)
}
}
@@ -81,8 +81,8 @@ struct ColorsDemo {
return ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
}()
}

View File

@@ -158,8 +158,7 @@ final class ListObserverDemoViewController: UITableViewController {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
@@ -171,8 +170,8 @@ final class ListObserverDemoViewController: UITableViewController {
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue()
palette.colorName .= nil
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }

View File

@@ -43,7 +43,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
required init?(coder aDecoder: NSCoder) {
if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue))) {
if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue))) {
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
@@ -52,12 +52,11 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
_ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
_ = transaction.create(Into<Palette>())
}
)
let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue)))!
let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue)))!
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
@@ -119,7 +118,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) {
palette.hue .= Int(hue)
palette.hue = Int(hue)
}
},
completion: { _ in }
@@ -134,7 +133,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation .= saturation
palette.saturation = saturation
}
},
completion: { _ in }
@@ -149,7 +148,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness .= brightness
palette.brightness = brightness
}
},
completion: { _ in }
@@ -169,7 +168,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName.value
self.colorNameLabel?.text = palette.colorName
let color = palette.color
self.colorNameLabel?.textColor = color
@@ -177,17 +176,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.hue)) == true {
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$hue)) == true {
self.hueSlider?.value = Float(palette.hue.value)
self.hueSlider?.value = Float(palette.hue)
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.saturation)) == true {
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$saturation)) == true {
self.saturationSlider?.value = palette.saturation.value
self.saturationSlider?.value = palette.saturation
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.brightness)) == true {
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$brightness)) == true {
self.brightnessSlider?.value = palette.brightness.value
self.brightnessSlider?.value = palette.brightness
}
}
}

View File

@@ -16,44 +16,53 @@ import CoreStore
final class Palette: CoreStoreObject {
let hue = Value.Required<Int>("hue", initial: 0)
let saturation = Value.Required<Float>("saturation", initial: 0)
let brightness = Value.Required<Float>("brightness", initial: 0)
let colorName = Value.Optional<String>(
"colorName",
isTransient: true,
customGetter: Palette.getColorName
@Field.Stored(
"hue",
dynamicInitialValue: { Palette.randomHue() }
)
var hue: Int
static func randomHue() -> Int {
return Int(arc4random_uniform(360))
}
@Field.Stored("saturation")
var saturation: Float = 1
private static func getColorName(_ partialObject: PartialObject<Palette>) -> String? {
if let colorName = partialObject.primitiveValue(for: { $0.colorName }) {
@Field.Stored(
"brightness",
dynamicInitialValue: { Palette.randomBrightness() }
)
var brightness: Float
@Field.Virtual(
"colorName",
customGetter: { object, field in
if let colorName = field.primitiveValue {
return colorName
}
let colorName: String
switch object.$hue.value % 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"
}
field.primitiveValue = colorName
return colorName
}
)
var colorName: String!
static func randomHue() -> Int {
let colorName: String
switch partialObject.value(for: { $0.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"
}
return Int.random(in: 0 ..< 360)
}
static func randomBrightness() -> Float {
partialObject.setPrimitiveValue(colorName, for: { $0.colorName })
return colorName
return (Float.random(in: 0 ..< 70) + 30) / 100.0
}
}
@@ -62,25 +71,15 @@ extension Palette {
var color: UIColor {
return UIColor(
hue: CGFloat(self.hue.value) / 360.0,
saturation: CGFloat(self.saturation.value),
brightness: CGFloat(self.brightness.value),
hue: CGFloat(self.hue) / 360.0,
saturation: CGFloat(self.saturation),
brightness: CGFloat(self.brightness),
alpha: 1.0
)
}
var colorText: String {
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%"
}
}
extension Palette {
func setInitialValues(in transaction: BaseDataTransaction) {
self.hue .= Palette.randomHue()
self.saturation .= Float(1.0)
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
}
}

View File

@@ -33,8 +33,8 @@ final class SwiftUIContainerViewController: UIViewController {
rootView: SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)

View File

@@ -61,8 +61,8 @@ struct SwiftUIView: View {
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue()
palette.colorName .= nil
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
@@ -79,8 +79,7 @@ struct SwiftUIView: View {
self.dataStack.perform(
asynchronous: { transaction in
let palette = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
@@ -173,8 +172,8 @@ struct SwiftUIView_Previews: PreviewProvider {
SwiftUIView(
palettes: ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.colorName)
.orderBy(.ascending(\.hue))
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
)
.environment(\.dataStack, ColorsDemo.stack)