WIP: documentation

This commit is contained in:
John Rommel Estropia
2017-05-12 01:42:19 +09:00
parent 66bef87422
commit 9c25336ff6
4 changed files with 446 additions and 172 deletions

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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`.
*/

View File

@@ -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 {