mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-14 13:13:33 +01:00
WIP: documentation
This commit is contained in:
@@ -33,6 +33,7 @@ class Animal: CoreStoreObject {
|
||||
|
||||
let species = Value.Required<String>("species", default: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
|
||||
class Dog: Animal {
|
||||
@@ -69,12 +70,12 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Dog>("Dog"),
|
||||
Entity<Person>("Person")
|
||||
]/*,
|
||||
],
|
||||
versionLock: [
|
||||
"Animal": [0x2698c812ebbc3b97, 0x751e3fa3f04cf9, 0x51fd460d3babc82, 0x92b4ba735b5a3053],
|
||||
"Dog": [0x5285f8e3aff69199, 0x62c3291b59f2ec7c, 0xbe5a571397a4117b, 0x97fb40f5b79ffbdc],
|
||||
"Person": [0xae4060a59f990ef0, 0x8ac83a6e1411c130, 0xa29fea58e2e38ab6, 0x2071bb7e33d77887]
|
||||
]*/
|
||||
"Animal": [0x1b59d511019695cf, 0xdeb97e86c5eff179, 0x1cfd80745646cb3, 0x4ff99416175b5b9a],
|
||||
"Dog": [0xe3f0afeb109b283a, 0x29998d292938eb61, 0x6aab788333cfc2a3, 0x492ff1d295910ea7],
|
||||
"Person": [0x66d8bbfd8b21561f, 0xcecec69ecae3570f, 0xc4b73d71256214ef, 0x89b99bfe3e013e8b]
|
||||
]
|
||||
)
|
||||
)
|
||||
self.prepareStack(dataStack, configurations: [nil]) { (stack) in
|
||||
@@ -100,6 +101,9 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
animal.species .= "Sparrow"
|
||||
XCTAssertEqual(animal.species.value, "Sparrow")
|
||||
|
||||
animal.color .= .yellow
|
||||
XCTAssertEqual(animal.color.value, UIColor.yellow)
|
||||
|
||||
let dog = transaction.create(Into<Dog>())
|
||||
XCTAssertEqual(dog.species.value, "Swift")
|
||||
XCTAssertEqual(dog.nickname.value, nil)
|
||||
|
||||
@@ -27,11 +27,6 @@ import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
|
||||
|
||||
// MARK: - DynamicObject
|
||||
|
||||
public extension DynamicObject where Self: CoreStoreObject {
|
||||
@@ -48,18 +43,6 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
public final class ToOne<D: CoreStoreObject>: RelationshipProtocol {
|
||||
|
||||
// MARK: -
|
||||
|
||||
public static func .= (_ relationship: RelationshipContainer<O>.ToOne<D>, _ value: D?) {
|
||||
|
||||
relationship.value = value
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) {
|
||||
|
||||
relationship.value = relationship2.value
|
||||
}
|
||||
|
||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
@@ -150,21 +133,6 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
public final class ToManyOrdered<D: CoreStoreObject>: RelationshipProtocol {
|
||||
|
||||
public static func .= (_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ value: [D]) {
|
||||
|
||||
relationship.value = value
|
||||
}
|
||||
|
||||
public static func .=<C: Collection> (_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ value: C) where C.Iterator.Element == D {
|
||||
|
||||
relationship.value = Array(value)
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.value = relationship2.value
|
||||
}
|
||||
|
||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
@@ -271,28 +239,6 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
public final class ToManyUnordered<D: CoreStoreObject>: RelationshipProtocol {
|
||||
|
||||
// MARK: -
|
||||
|
||||
public static func .= (_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ value: Set<D>) {
|
||||
|
||||
relationship.value = value
|
||||
}
|
||||
|
||||
public static func .=<C: Collection> (_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ value: C) where C.Iterator.Element == D {
|
||||
|
||||
relationship.value = Set(value)
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) {
|
||||
|
||||
relationship.value = relationship2.value
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.value = Set(relationship2.value)
|
||||
}
|
||||
|
||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||
|
||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||
@@ -416,7 +362,7 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
}
|
||||
|
||||
|
||||
// MARK: RelationshipContainer.ToManyOrdered: RandomAccessCollection
|
||||
// MARK: - Convenience
|
||||
|
||||
extension RelationshipContainer.ToManyOrdered: RandomAccessCollection {
|
||||
|
||||
@@ -456,9 +402,6 @@ extension RelationshipContainer.ToManyOrdered: RandomAccessCollection {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: RelationshipContainer.ToManyUnordered: Sequence
|
||||
|
||||
extension RelationshipContainer.ToManyUnordered: Sequence {
|
||||
|
||||
public var count: Int {
|
||||
@@ -484,6 +427,117 @@ extension RelationshipContainer.ToManyUnordered: Sequence {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Operations
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
infix operator .== : ComparisonPrecedence
|
||||
|
||||
extension RelationshipContainer.ToOne {
|
||||
|
||||
public static func .= (_ relationship: RelationshipContainer<O>.ToOne<D>, _ newValue: D?) {
|
||||
|
||||
relationship.value = newValue
|
||||
}
|
||||
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) {
|
||||
|
||||
relationship.value = relationship2.value
|
||||
}
|
||||
|
||||
public static func .== (_ relationship: RelationshipContainer<O>.ToOne<D>, _ value: D?) -> Bool {
|
||||
|
||||
return relationship.value == value
|
||||
}
|
||||
|
||||
public static func .== (_ value: D?, _ relationship: RelationshipContainer<O>.ToOne<D>) -> Bool {
|
||||
|
||||
return value == relationship.value
|
||||
}
|
||||
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToOne<D>, _ relationship2: RelationshipContainer<O2>.ToOne<D>) -> Bool {
|
||||
|
||||
return relationship.value == relationship2.value
|
||||
}
|
||||
}
|
||||
|
||||
extension RelationshipContainer.ToManyOrdered {
|
||||
|
||||
public static func .= <S: Sequence>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ newValue: S) where S.Iterator.Element == D {
|
||||
|
||||
relationship.nativeValue = NSOrderedSet(array: newValue.map({ $0.rawObject! }))
|
||||
}
|
||||
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.nativeValue = relationship2.nativeValue
|
||||
}
|
||||
|
||||
public static func .== <C: Collection>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ collection: C) -> Bool where C.Iterator.Element == D {
|
||||
|
||||
return relationship.nativeValue.elementsEqual(
|
||||
collection.lazy.map({ $0.rawObject! }),
|
||||
by: { ($0 as! NSManagedObject) == ($1 as! NSManagedObject) }
|
||||
)
|
||||
}
|
||||
|
||||
public static func .== <C: Collection>(_ collection: C, _ relationship: RelationshipContainer<O>.ToManyOrdered<D>) -> Bool where C.Iterator.Element == D {
|
||||
|
||||
return relationship.nativeValue.elementsEqual(
|
||||
collection.lazy.map({ $0.rawObject! }),
|
||||
by: { ($0 as! NSManagedObject) == ($1 as! NSManagedObject) }
|
||||
)
|
||||
}
|
||||
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue == relationship2.nativeValue
|
||||
}
|
||||
}
|
||||
|
||||
extension RelationshipContainer.ToManyUnordered {
|
||||
|
||||
public static func .= <S: Sequence>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ newValue: S) where S.Iterator.Element == D {
|
||||
|
||||
relationship.nativeValue = NSSet(array: newValue.map({ $0.rawObject! }))
|
||||
}
|
||||
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) {
|
||||
|
||||
relationship.nativeValue = relationship2.nativeValue
|
||||
}
|
||||
|
||||
public static func .= <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) {
|
||||
|
||||
relationship.nativeValue = NSSet(set: relationship2.nativeValue.set)
|
||||
}
|
||||
|
||||
public static func .== <S: Sequence>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ sequence: S) -> Bool where S.Iterator.Element == D {
|
||||
|
||||
return relationship.nativeValue.isEqual(to: Set(sequence.map({ $0.rawObject! })))
|
||||
}
|
||||
|
||||
public static func .== <S: Sequence>(_ sequence: S, _ relationship: RelationshipContainer<O>.ToManyUnordered<D>) -> Bool where S.Iterator.Element == D {
|
||||
|
||||
return relationship.nativeValue.isEqual(to: Set(sequence.map({ $0.rawObject! })))
|
||||
}
|
||||
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue == relationship2.nativeValue
|
||||
}
|
||||
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyUnordered<D>, _ relationship2: RelationshipContainer<O2>.ToManyOrdered<D>) -> Bool {
|
||||
|
||||
return relationship.nativeValue == NSSet(set: relationship2.nativeValue.set)
|
||||
}
|
||||
|
||||
public static func .== <O2: CoreStoreObject>(_ relationship: RelationshipContainer<O>.ToManyOrdered<D>, _ relationship2: RelationshipContainer<O2>.ToManyUnordered<D>) -> Bool {
|
||||
|
||||
return NSSet(set: relationship.nativeValue.set) == relationship2.nativeValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - RelationshipProtocol
|
||||
|
||||
internal protocol RelationshipProtocol: class {
|
||||
|
||||
@@ -39,6 +39,14 @@ public final class SchemaHistory: ExpressibleByArrayLiteral {
|
||||
*/
|
||||
public let currentModelVersion: ModelVersion
|
||||
|
||||
/**
|
||||
The schema for the current model version. The `DataStack` will try to migrate all `StorageInterface`s added to itself to this version, following the version steps provided by the `migrationChain`.
|
||||
*/
|
||||
public var currentSchema: DynamicSchema {
|
||||
|
||||
return self.schema(for: self.currentModelVersion)!
|
||||
}
|
||||
|
||||
/**
|
||||
The version string for the current model version. The `DataStack` will try to migrate all `StorageInterface`s added to itself to this version, following the version steps provided by the `migrationChain`.
|
||||
*/
|
||||
|
||||
@@ -27,32 +27,29 @@ import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
|
||||
|
||||
// MARK: - DynamicObject
|
||||
|
||||
public extension DynamicObject where Self: CoreStoreObject {
|
||||
|
||||
/**
|
||||
The containing type for value attributes. `Value` attributes support any type that conform to `ImportableAttributeType`.
|
||||
The containing type for value attributes. `Value` attributes support any type that conforms to `ImportableAttributeType`.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public typealias Value = ValueContainer<Self>
|
||||
|
||||
/**
|
||||
The containing type for transformable attributes. `Transformable` attributes support types that conform to `NSCoding` and `NSCopying`.
|
||||
The containing type for transformable attributes. `Transformable` attributes support types that conforms to `NSCoding & NSCopying`.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let ancestors = Transformable.Required<NSArray>("ancestors")
|
||||
let descendants = Transformable.Optional<NSDictionary>("descendants")
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
@@ -68,54 +65,54 @@ public extension DynamicObject where Self: CoreStoreObject {
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public enum ValueContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: - Required
|
||||
|
||||
/**
|
||||
The containing type for required value attributes. Any type that conform to `ImportableAttributeType` are supported.
|
||||
The containing type for required value attributes. Any type that conforms to `ImportableAttributeType` are supported.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public final class Required<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
Initializes the metadata for the attribute.
|
||||
```
|
||||
animal.species .= "Swift"
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.species.value = "Swift"
|
||||
class Person: CoreStoreObject {
|
||||
let title = Value.Required<String>("title", default: "Mr.")
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customGetter: { (`self`, getValue) in
|
||||
return "\(self.title.value) \(getValue())"
|
||||
}
|
||||
)
|
||||
}
|
||||
```
|
||||
- parameter keyPath: the permanent attribute name for this attribute.
|
||||
- parameter default: the initial value for the property when the object is first created. Defaults to the `ImportableAttributeType`'s empty value if not specified.
|
||||
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
|
||||
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the attributes of a property are unchanged but the format or content of its data are changed.)
|
||||
- parameter renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's name.
|
||||
- parameter customGetter: use this closure to make final transformations to the property's value before returning from the getter.
|
||||
- parameter self: the `CoreStoreObject`
|
||||
- parameter getValue: the original getter for the property
|
||||
- parameter customSetter: use this closure to make final transformations to the new value before assigning to the property.
|
||||
- parameter setValue: the original setter for the property
|
||||
- parameter finalNewValue: the transformed new value
|
||||
- parameter originalNewValue: the original new value
|
||||
*/
|
||||
public static func .= (_ attribute: ValueContainer<O>.Required<V>, _ value: V) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
```
|
||||
animal.species .= anotherAnimal.species
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.species.value = anotherAnimal.species.value
|
||||
```
|
||||
*/
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: ValueContainer<O>.Required<V>, _ attribute2: ValueContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath, `default`: V = V.cs_emptyValue(), isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
||||
public init(_ keyPath: KeyPath, `default`: V = V.cs_emptyValue(), isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V) -> Void, _ originalNewValue: V) -> Void = { $1($2) }) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.isIndexed = isIndexed
|
||||
@@ -127,6 +124,9 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
self.customSetter = customSetter
|
||||
}
|
||||
|
||||
/**
|
||||
The property value.
|
||||
*/
|
||||
public var value: V {
|
||||
|
||||
get {
|
||||
@@ -206,64 +206,48 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
// MARK: - Optional
|
||||
|
||||
/**
|
||||
The containing type for optional value attributes. Any type that conform to `ImportableAttributeType` are supported.
|
||||
The containing type for optional value attributes. Any type that conforms to `ImportableAttributeType` are supported.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public final class Optional<V: ImportableAttributeType>: AttributeProtocol {
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
Initializes the metadata for the attribute.
|
||||
```
|
||||
animal.nickname .= "Taylor"
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = "Taylor"
|
||||
class Person: CoreStoreObject {
|
||||
let title = Value.Required<String>("title", default: "Mr.")
|
||||
let name = Value.Required<String>(
|
||||
"name",
|
||||
customGetter: { (`self`, getValue) in
|
||||
return "\(self.title.value) \(getValue())"
|
||||
}
|
||||
)
|
||||
}
|
||||
```
|
||||
- parameter keyPath: the permanent attribute name for this attribute.
|
||||
- parameter default: the initial value for the property when the object is first created. Defaults to `nil` if not specified.
|
||||
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
|
||||
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the attributes of a property are unchanged but the format or content of its data are changed.)
|
||||
- parameter renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's name.
|
||||
- parameter customGetter: use this closure to make final transformations to the property's value before returning from the getter.
|
||||
- parameter self: the `CoreStoreObject`
|
||||
- parameter getValue: the original getter for the property
|
||||
- parameter customSetter: use this closure to make final transformations to the new value before assigning to the property.
|
||||
- parameter setValue: the original setter for the property
|
||||
- parameter finalNewValue: the transformed new value
|
||||
- parameter originalNewValue: the original new value
|
||||
*/
|
||||
public static func .= (_ attribute: ValueContainer<O>.Optional<V>, _ value: V?) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
```
|
||||
animal.nickname .= anotherAnimal.nickname
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = anotherAnimal.nickname.value
|
||||
```
|
||||
*/
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: ValueContainer<O>.Optional<V>, _ attribute2: ValueContainer<O2>.Optional<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
```
|
||||
animal.nickname .= anotherAnimal.nickname
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = anotherAnimal.nickname.value
|
||||
```
|
||||
*/
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: ValueContainer<O>.Optional<V>, _ attribute2: ValueContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V?) -> Void, _ originalNewValue: V?) -> Void = { $1($2) }) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.isIndexed = isIndexed
|
||||
self.isTransient = isTransient
|
||||
self.defaultValue = `default`?.cs_toImportableNativeType()
|
||||
self.versionHashModifier = versionHashModifier
|
||||
@@ -272,6 +256,9 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
self.customSetter = customSetter
|
||||
}
|
||||
|
||||
/**
|
||||
The property value.
|
||||
*/
|
||||
public var value: V? {
|
||||
|
||||
get {
|
||||
@@ -328,7 +315,7 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
|
||||
public let keyPath: KeyPath
|
||||
internal let isOptional = true
|
||||
internal let isIndexed = false
|
||||
internal let isIndexed: Bool
|
||||
internal let isTransient: Bool
|
||||
internal let defaultValue: Any?
|
||||
internal let versionHashModifier: String?
|
||||
@@ -350,23 +337,54 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: - TransformableContainer
|
||||
|
||||
/**
|
||||
The containing type for transformable attributes. Use the `DynamicObject.Transformable` typealias instead for shorter syntax.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public enum TransformableContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: - Required
|
||||
|
||||
/**
|
||||
The containing type for transformable attributes. Any type that conforms to `NSCoding & NSCopying` are supported.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public final class Required<V: NSCoding & NSCopying>: AttributeProtocol {
|
||||
|
||||
public static func .= (_ attribute: TransformableContainer<O>.Required<V>, _ value: V) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: TransformableContainer<O>.Required<V>, _ attribute2: TransformableContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
||||
/**
|
||||
Initializes the metadata for the attribute.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
- parameter keyPath: the permanent attribute name for this attribute.
|
||||
- parameter default: the initial value for the property when the object is first created. Defaults to the `ImportableAttributeType`'s empty value if not specified.
|
||||
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
|
||||
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the attributes of a property are unchanged but the format or content of its data are changed.)
|
||||
- parameter renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's name.
|
||||
- parameter customGetter: use this closure to make final transformations to the property's value before returning from the getter.
|
||||
- parameter self: the `CoreStoreObject`
|
||||
- parameter getValue: the original getter for the property
|
||||
- parameter customSetter: use this closure to make final transformations to the new value before assigning to the property.
|
||||
- parameter setValue: the original setter for the property
|
||||
- parameter finalNewValue: the transformed new value
|
||||
- parameter originalNewValue: the original new value
|
||||
*/
|
||||
public init(_ keyPath: KeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V) -> Void, _ originalNewValue: V) -> Void = { $1($2) }) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`
|
||||
@@ -378,6 +396,9 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
||||
self.customSetter = customSetter
|
||||
}
|
||||
|
||||
/**
|
||||
The property value.
|
||||
*/
|
||||
public var value: V {
|
||||
|
||||
get {
|
||||
@@ -455,24 +476,40 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
||||
|
||||
// MARK: - Optional
|
||||
|
||||
/**
|
||||
The containing type for optional transformable attributes. Any type that conforms to `NSCoding & NSCopying` are supported.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species")
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
*/
|
||||
public final class Optional<V: NSCoding & NSCopying>: AttributeProtocol {
|
||||
|
||||
public static func .= (_ attribute: TransformableContainer<O>.Optional<V>, _ value: V) {
|
||||
|
||||
attribute.value = value
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: TransformableContainer<O>.Optional<V>, _ attribute2: TransformableContainer<O2>.Optional<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
public static func .=<O2: CoreStoreObject> (_ attribute: TransformableContainer<O>.Optional<V>, _ attribute2: TransformableContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
||||
/**
|
||||
Initializes the metadata for the attribute.
|
||||
```
|
||||
class Animal: CoreStoreObject {
|
||||
let color = Transformable.Optional<UIColor>("color")
|
||||
}
|
||||
```
|
||||
- parameter keyPath: the permanent attribute name for this attribute.
|
||||
- parameter default: the initial value for the property when the object is first created. Defaults to the `ImportableAttributeType`'s empty value if not specified.
|
||||
- parameter isIndexed: `true` if the property should be indexed for searching, otherwise `false`. Defaults to `false` if not specified.
|
||||
- parameter isTransient: `true` if the property is transient, otherwise `false`. Defaults to `false` if not specified. The transient flag specifies whether or not a property's value is ignored when an object is saved to a persistent store. Transient properties are not saved to the persistent store, but are still managed for undo, redo, validation, and so on.
|
||||
- parameter versionHashModifier: used to mark or denote a property as being a different "version" than another even if all of the values which affect persistence are equal. (Such a difference is important in cases where the attributes of a property are unchanged but the format or content of its data are changed.)
|
||||
- parameter renamingIdentifier: used to resolve naming conflicts between models. When creating an entity mapping between entities in two managed object models, a source entity property and a destination entity property that share the same identifier indicate that a property mapping should be configured to migrate from the source to the destination. If unset, the identifier will be the property's name.
|
||||
- parameter customGetter: use this closure to make final transformations to the property's value before returning from the getter.
|
||||
- parameter self: the `CoreStoreObject`
|
||||
- parameter getValue: the original getter for the property
|
||||
- parameter customSetter: use this closure to make final transformations to the new value before assigning to the property.
|
||||
- parameter setValue: the original setter for the property
|
||||
- parameter finalNewValue: the transformed new value
|
||||
- parameter originalNewValue: the original new value
|
||||
*/
|
||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (_ finalNewValue: V?) -> Void, _ originalNewValue: V?) -> Void = { $1($2) }) {
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.defaultValue = `default`
|
||||
@@ -484,6 +521,9 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
||||
self.customSetter = customSetter
|
||||
}
|
||||
|
||||
/**
|
||||
The property value.
|
||||
*/
|
||||
public var value: V? {
|
||||
|
||||
get {
|
||||
@@ -539,7 +579,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
||||
|
||||
public let keyPath: KeyPath
|
||||
|
||||
internal let isOptional = false
|
||||
internal let isOptional = true
|
||||
internal let isIndexed: Bool
|
||||
internal let isTransient: Bool
|
||||
internal let defaultValue: Any?
|
||||
@@ -560,6 +600,174 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Operations
|
||||
|
||||
infix operator .= : AssignmentPrecedence
|
||||
infix operator .== : ComparisonPrecedence
|
||||
|
||||
extension ValueContainer.Required {
|
||||
|
||||
/**
|
||||
Assigns a value to the attribute. The operation
|
||||
```
|
||||
animal.species .= "Swift"
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.species.value = "Swift"
|
||||
```
|
||||
*/
|
||||
public static func .= (_ attribute: ValueContainer<O>.Required<V>, _ newValue: V) {
|
||||
|
||||
attribute.value = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a value from another attribute. The operation
|
||||
```
|
||||
animal.species .= anotherAnimal.species
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.species.value = anotherAnimal.species.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: ValueContainer<O>.Required<V>, _ attribute2: ValueContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
}
|
||||
|
||||
extension ValueContainer.Optional {
|
||||
|
||||
/**
|
||||
Assigns an optional value to the attribute. The operation
|
||||
```
|
||||
animal.nickname .= "Taylor"
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = "Taylor"
|
||||
```
|
||||
*/
|
||||
public static func .= (_ attribute: ValueContainer<O>.Optional<V>, _ newValue: V?) {
|
||||
|
||||
attribute.value = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns an optional value from another attribute. The operation
|
||||
```
|
||||
animal.nickname .= anotherAnimal.nickname
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = anotherAnimal.nickname.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: ValueContainer<O>.Optional<V>, _ attribute2: ValueContainer<O2>.Optional<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a value from another attribute. The operation
|
||||
```
|
||||
animal.nickname .= anotherAnimal.species
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = anotherAnimal.species.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: ValueContainer<O>.Optional<V>, _ attribute2: ValueContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformableContainer.Required {
|
||||
|
||||
/**
|
||||
Assigns a transformable value to the attribute. The operation
|
||||
```
|
||||
animal.color .= UIColor.red
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.color.value = UIColor.red
|
||||
```
|
||||
*/
|
||||
public static func .= (_ attribute: TransformableContainer<O>.Required<V>, _ newValue: V) {
|
||||
|
||||
attribute.value = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a transformable value from another attribute. The operation
|
||||
```
|
||||
animal.nickname .= anotherAnimal.species
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.nickname.value = anotherAnimal.species.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: TransformableContainer<O>.Required<V>, _ attribute2: TransformableContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformableContainer.Optional {
|
||||
|
||||
/**
|
||||
Assigns an optional transformable value to the attribute. The operation
|
||||
```
|
||||
animal.color .= UIColor.red
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.color.value = UIColor.red
|
||||
```
|
||||
*/
|
||||
public static func .= (_ attribute: TransformableContainer<O>.Optional<V>, _ newValue: V?) {
|
||||
|
||||
attribute.value = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns an optional transformable value from another attribute. The operation
|
||||
```
|
||||
animal.color .= anotherAnimal.color
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.color.value = anotherAnimal.color.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: TransformableContainer<O>.Optional<V>, _ attribute2: TransformableContainer<O2>.Optional<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
|
||||
/**
|
||||
Assigns a transformable value from another attribute. The operation
|
||||
```
|
||||
animal.color .= anotherAnimal.color
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
animal.color.value = anotherAnimal.color.value
|
||||
```
|
||||
*/
|
||||
public static func .= <O2: CoreStoreObject>(_ attribute: TransformableContainer<O>.Optional<V>, _ attribute2: TransformableContainer<O2>.Required<V>) {
|
||||
|
||||
attribute.value = attribute2.value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - AttributeProtocol
|
||||
|
||||
internal protocol AttributeProtocol: class {
|
||||
|
||||
Reference in New Issue
Block a user