mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-30 06:11:50 +02:00
updated documentation (fixes #198)
This commit is contained in:
@@ -1675,7 +1675,7 @@ To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C sour
|
|||||||
Starting CoreStore 4.0, we can now create persisted objects without depending on *.xcdatamodeld* Core Data files. The new `CoreStoreObject` subclass replaces `NSManagedObject`, and specially-typed properties declared on these classes will be synthesized as Core Data attributes.
|
Starting CoreStore 4.0, we can now create persisted objects without depending on *.xcdatamodeld* Core Data files. The new `CoreStoreObject` subclass replaces `NSManagedObject`, and specially-typed properties declared on these classes will be synthesized as Core Data attributes.
|
||||||
```swift
|
```swift
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dog: Animal {
|
class Dog: Animal {
|
||||||
@@ -1684,14 +1684,14 @@ class Dog: Animal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
|
let pets = Relationship.ToManyUnordered<Dog>("pets", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The property names to be saved to Core Data is specified as the `keyPath` argument. This lets us refactor our Swift code without affecting the underlying database. For example:
|
The property names to be saved to Core Data is specified as the `keyPath` argument. This lets us refactor our Swift code without affecting the underlying database. For example:
|
||||||
```swift
|
```swift
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
private let _name = Value.Required<String>("name")
|
private let _name = Value.Required<String>("name", initial: "")
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -47,12 +47,6 @@ public enum LogLevel {
|
|||||||
*/
|
*/
|
||||||
public protocol CoreStoreLogger {
|
public protocol CoreStoreLogger {
|
||||||
|
|
||||||
/**
|
|
||||||
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false` if not implemented.
|
|
||||||
*/
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// var enableObjectConcurrencyDebugging: Bool { get set }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handles log messages sent by the `CoreStore` framework.
|
Handles log messages sent by the `CoreStore` framework.
|
||||||
|
|
||||||
@@ -100,13 +94,6 @@ public protocol CoreStoreLogger {
|
|||||||
|
|
||||||
extension CoreStoreLogger {
|
extension CoreStoreLogger {
|
||||||
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// public var enableObjectConcurrencyDebugging: Bool {
|
|
||||||
//
|
|
||||||
// get { return false }
|
|
||||||
// set {}
|
|
||||||
// }
|
|
||||||
|
|
||||||
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||||
|
|
||||||
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ import Foundation
|
|||||||
The `CoreStoreObject` is an abstract class for creating CoreStore-managed objects that are more type-safe and more convenient than `NSManagedObject` subclasses. The model entities for `CoreStoreObject` subclasses are inferred from the Swift declaration themselves; no .xcdatamodeld files are needed. To declare persisted attributes and relationships for the `CoreStoreObject` subclass, declare properties of type `Value.Required<T>`, `Value.Optional<T>` for values, or `Relationship.ToOne<T>`, `Relationship.ToManyOrdered<T>`, `Relationship.ToManyUnordered<T>` for relationships.
|
The `CoreStoreObject` is an abstract class for creating CoreStore-managed objects that are more type-safe and more convenient than `NSManagedObject` subclasses. The model entities for `CoreStoreObject` subclasses are inferred from the Swift declaration themselves; no .xcdatamodeld files are needed. To declare persisted attributes and relationships for the `CoreStoreObject` subclass, declare properties of type `Value.Required<T>`, `Value.Optional<T>` for values, or `Relationship.ToOne<T>`, `Relationship.ToManyOrdered<T>`, `Relationship.ToManyUnordered<T>` for relationships.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let master = Relationship.ToOne<Person>("master")
|
let master = Relationship.ToOne<Person>("master")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -141,6 +141,9 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable {
|
|||||||
|
|
||||||
public extension DynamicObject where Self: CoreStoreObject {
|
public extension DynamicObject where Self: CoreStoreObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the `PartialObject` instance for the object, which acts as a fast, type-safe KVC interface for `CoreStoreObject`.
|
||||||
|
*/
|
||||||
public func partialObject() -> PartialObject<Self> {
|
public func partialObject() -> PartialObject<Self> {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ import Foundation
|
|||||||
The `CoreStoreSchema` describes models written for `CoreStoreObject` Swift class declarations for a particular model version. `CoreStoreObject` entities for a model version should be added to `CoreStoreSchema` instance.
|
The `CoreStoreSchema` describes models written for `CoreStoreObject` Swift class declarations for a particular model version. `CoreStoreObject` entities for a model version should be added to `CoreStoreSchema` instance.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let master = Relationship.ToOne<Person>("master")
|
let master = Relationship.ToOne<Person>("master")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,13 +66,13 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
Initializes a `CoreStoreSchema`. Using this initializer only if the entities don't need to be assigned to particular "Configurations". To use multiple configurations (for example, to separate entities in different `StorageInterface`s), use the `init(modelVersion:entitiesByConfiguration:versionLock:)` initializer.
|
Initializes a `CoreStoreSchema`. Using this initializer only if the entities don't need to be assigned to particular "Configurations". To use multiple configurations (for example, to separate entities in different `StorageInterface`s), use the `init(modelVersion:entitiesByConfiguration:versionLock:)` initializer.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let master = Relationship.ToOne<Person>("master")
|
let master = Relationship.ToOne<Person>("master")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +112,12 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
Initializes a `CoreStoreSchema`. Using this initializer if multiple "Configurations" (for example, to separate entities in different `StorageInterface`s) are needed. To add an entity only to the default configuration, assign an empty set to its configurations list. Note that regardless of the set configurations, all entities will be added to the default configuration.
|
Initializes a `CoreStoreSchema`. Using this initializer if multiple "Configurations" (for example, to separate entities in different `StorageInterface`s) are needed. To add an entity only to the default configuration, assign an empty set to its configurations list. Note that regardless of the set configurations, all entities will be added to the default configuration.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreStore.defaultStack = DataStack(
|
CoreStore.defaultStack = DataStack(
|
||||||
|
|||||||
@@ -105,9 +105,6 @@ public final class DataStack: Equatable {
|
|||||||
*/
|
*/
|
||||||
public required init(schemaHistory: SchemaHistory) {
|
public required init(schemaHistory: SchemaHistory) {
|
||||||
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// _ = DataStack.isGloballyInitialized
|
|
||||||
|
|
||||||
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
|
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
|
||||||
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
||||||
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
|
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
|
||||||
@@ -585,13 +582,6 @@ public final class DataStack: Equatable {
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// private static let isGloballyInitialized: Bool = {
|
|
||||||
//
|
|
||||||
// NSManagedObject.cs_swizzleMethodsForLogging()
|
|
||||||
// return true
|
|
||||||
// }()
|
|
||||||
|
|
||||||
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
|
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
|
||||||
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
|
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,6 @@ import Foundation
|
|||||||
*/
|
*/
|
||||||
public final class DefaultLogger: CoreStoreLogger {
|
public final class DefaultLogger: CoreStoreLogger {
|
||||||
|
|
||||||
/**
|
|
||||||
When `true`, all `NSManagedObject` attribute and relationship access will raise an assertion when executed on the wrong transaction/datastack queue. Defaults to `false`.
|
|
||||||
*/
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// public var enableObjectConcurrencyDebugging: Bool = false
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a `DefaultLogger`.
|
Creates a `DefaultLogger`.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ import ObjectiveC
|
|||||||
The `Entity<O>` contains `NSEntityDescription` metadata for `CoreStoreObject` subclasses. Pass the `Entity` instances to `CoreStoreSchema` initializer.
|
The `Entity<O>` contains `NSEntityDescription` metadata for `CoreStoreObject` subclasses. Pass the `Entity` instances to `CoreStoreSchema` initializer.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let master = Relationship.ToOne<Person>("master")
|
let master = Relationship.ToOne<Person>("master")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -425,8 +425,6 @@ public final class ICloudStore: CloudStorage {
|
|||||||
*/
|
*/
|
||||||
public func cs_eraseStorageAndWait(soureModel: NSManagedObjectModel) throws {
|
public func cs_eraseStorageAndWait(soureModel: NSManagedObjectModel) throws {
|
||||||
|
|
||||||
// TODO: check if attached to persistent store
|
|
||||||
|
|
||||||
let cacheFileURL = self.cacheFileURL
|
let cacheFileURL = self.cacheFileURL
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
|
|||||||
@@ -66,212 +66,4 @@ internal extension NSManagedObject {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test before release (rolled back)
|
|
||||||
// @nonobjc
|
|
||||||
// internal static func cs_swizzleMethodsForLogging() {
|
|
||||||
//
|
|
||||||
// struct Static {
|
|
||||||
//
|
|
||||||
// static let isSwizzled = Static.swizzle()
|
|
||||||
//
|
|
||||||
// private static func swizzle() -> Bool {
|
|
||||||
//
|
|
||||||
// NSManagedObject.cs_swizzle(
|
|
||||||
// original: #selector(NSManagedObject.willAccessValue(forKey:)),
|
|
||||||
// proxy: #selector(NSManagedObject.cs_willAccessValue(forKey:))
|
|
||||||
// )
|
|
||||||
// NSManagedObject.cs_swizzle(
|
|
||||||
// original: #selector(NSManagedObject.willChangeValue(forKey:)),
|
|
||||||
// proxy: #selector(NSManagedObject.cs_willChangeValue(forKey:))
|
|
||||||
// )
|
|
||||||
// NSManagedObject.cs_swizzle(
|
|
||||||
// original: #selector(NSManagedObject.willChangeValue(forKey:withSetMutation:using:)),
|
|
||||||
// proxy: #selector(NSManagedObject.cs_willChangeValue(forKey:withSetMutation:using:))
|
|
||||||
// )
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// assert(Static.isSwizzled)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @nonobjc
|
|
||||||
// private static func cs_swizzle(original originalSelector: Selector, proxy swizzledSelector: Selector) {
|
|
||||||
//
|
|
||||||
// let originalMethod = class_getInstanceMethod(NSManagedObject.self, originalSelector)
|
|
||||||
// let swizzledMethod = class_getInstanceMethod(NSManagedObject.self, swizzledSelector)
|
|
||||||
// let didAddMethod = class_addMethod(
|
|
||||||
// NSManagedObject.self,
|
|
||||||
// originalSelector,
|
|
||||||
// method_getImplementation(swizzledMethod),
|
|
||||||
// method_getTypeEncoding(swizzledMethod)
|
|
||||||
// )
|
|
||||||
// if didAddMethod {
|
|
||||||
//
|
|
||||||
// class_replaceMethod(
|
|
||||||
// NSManagedObject.self,
|
|
||||||
// swizzledSelector,
|
|
||||||
// method_getImplementation(originalMethod),
|
|
||||||
// method_getTypeEncoding(originalMethod)
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
//
|
|
||||||
// method_exchangeImplementations(originalMethod, swizzledMethod)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private dynamic func cs_willAccessValue(forKey key: String?) {
|
|
||||||
//
|
|
||||||
// self.cs_willAccessValue(forKey: key)
|
|
||||||
//
|
|
||||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// guard let context = self.managedObjectContext else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isTransactionContext {
|
|
||||||
//
|
|
||||||
// guard let transaction = context.parentTransaction else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// transaction.isRunningInAllowedQueue(),
|
|
||||||
// "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isDataStackContext {
|
|
||||||
//
|
|
||||||
// guard context.parentStack != nil else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// Thread.isMainThread,
|
|
||||||
// "Attempted to access the \"\(key ?? "")\" key of an object of type \(cs_typeName(self)) outside the main thread."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private dynamic func cs_willChangeValue(forKey key: String?) {
|
|
||||||
//
|
|
||||||
// self.cs_willChangeValue(forKey: key)
|
|
||||||
//
|
|
||||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// guard let context = self.managedObjectContext else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isTransactionContext {
|
|
||||||
//
|
|
||||||
// guard let transaction = context.parentTransaction else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// transaction.isRunningInAllowedQueue(),
|
|
||||||
// "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isDataStackContext {
|
|
||||||
//
|
|
||||||
// guard context.parentStack != nil else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// Thread.isMainThread,
|
|
||||||
// "Attempted to change the \"\(key ?? "")\" of an object of type \(cs_typeName(self)) outside the main thread."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private dynamic func cs_willChangeValue(forKey inKey: String, withSetMutation inMutationKind: NSKeyValueSetMutationKind, using inObjects: Set<AnyHashable>) {
|
|
||||||
//
|
|
||||||
// self.cs_willChangeValue(
|
|
||||||
// forKey: inKey,
|
|
||||||
// withSetMutation: inMutationKind,
|
|
||||||
// using: inObjects
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// guard CoreStore.logger.enableObjectConcurrencyDebugging else {
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// guard let context = self.managedObjectContext else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(NSManagedObjectContext.self))."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isTransactionContext {
|
|
||||||
//
|
|
||||||
// guard let transaction = context.parentTransaction else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its transaction."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// transaction.isRunningInAllowedQueue(),
|
|
||||||
// "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) outside its transaction's designated queue."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if context.isDataStackContext {
|
|
||||||
//
|
|
||||||
// guard context.parentStack != nil else {
|
|
||||||
//
|
|
||||||
// CoreStore.log(
|
|
||||||
// .warning,
|
|
||||||
// message: "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) after has been deleted from its \(cs_typeName(DataStack.self)).")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// CoreStore.assert(
|
|
||||||
// Thread.isMainThread,
|
|
||||||
// "Attempted to mutate the \"\(inKey)\" of an object of type \(cs_typeName(self)) outside the main thread."
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ import Foundation
|
|||||||
*/
|
*/
|
||||||
public struct PartialObject<O: CoreStoreObject> {
|
public struct PartialObject<O: CoreStoreObject> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a the actual `CoreStoreObject` instance for the receiver.
|
||||||
|
*/
|
||||||
public func completeObject() -> O {
|
public func completeObject() -> O {
|
||||||
|
|
||||||
return O.cs_fromRaw(object: self.rawObject)
|
return O.cs_fromRaw(object: self.rawObject)
|
||||||
@@ -42,6 +45,9 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Value.Required accessors/mutators
|
// MARK: Value.Required accessors/mutators
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the property identified by a given key.
|
||||||
|
*/
|
||||||
public func value<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
public func value<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
||||||
|
|
||||||
return V.cs_fromQueryableNativeType(
|
return V.cs_fromQueryableNativeType(
|
||||||
@@ -49,6 +55,9 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the property of the receiver specified by a given key to a given value.
|
||||||
|
*/
|
||||||
public func setValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
public func setValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
||||||
|
|
||||||
self.rawObject.setValue(
|
self.rawObject.setValue(
|
||||||
@@ -57,6 +66,11 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the specified property from the managed object’s private internal storage.
|
||||||
|
|
||||||
|
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||||
|
*/
|
||||||
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Required<V>) -> V {
|
||||||
|
|
||||||
return V.cs_fromQueryableNativeType(
|
return V.cs_fromQueryableNativeType(
|
||||||
@@ -64,6 +78,11 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets in the object's private internal storage the value of a given property.
|
||||||
|
|
||||||
|
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||||
|
*/
|
||||||
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> ValueContainer<O>.Required<V>) {
|
||||||
|
|
||||||
self.rawObject.setPrimitiveValue(
|
self.rawObject.setPrimitiveValue(
|
||||||
@@ -75,12 +94,18 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Value.Optional utilities
|
// MARK: Value.Optional utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the property identified by a given key.
|
||||||
|
*/
|
||||||
public func value<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
public func value<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
||||||
|
|
||||||
return (self.rawObject.value(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
return (self.rawObject.value(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
||||||
.flatMap(V.cs_fromQueryableNativeType)
|
.flatMap(V.cs_fromQueryableNativeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the property of the receiver specified by a given key to a given value.
|
||||||
|
*/
|
||||||
public func setValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
public func setValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
||||||
|
|
||||||
self.rawObject.setValue(
|
self.rawObject.setValue(
|
||||||
@@ -89,12 +114,22 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the specified property from the managed object’s private internal storage.
|
||||||
|
|
||||||
|
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||||
|
*/
|
||||||
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
public func primitiveValue<V>(for property: (O) -> ValueContainer<O>.Optional<V>) -> V? {
|
||||||
|
|
||||||
return (self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
return (self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?)
|
||||||
.flatMap(V.cs_fromQueryableNativeType)
|
.flatMap(V.cs_fromQueryableNativeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets in the object's private internal storage the value of a given property.
|
||||||
|
|
||||||
|
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||||
|
*/
|
||||||
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> ValueContainer<O>.Optional<V>) {
|
||||||
|
|
||||||
self.rawObject.setPrimitiveValue(
|
self.rawObject.setPrimitiveValue(
|
||||||
@@ -106,11 +141,17 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Transformable.Required utilities
|
// MARK: Transformable.Required utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the property identified by a given key.
|
||||||
|
*/
|
||||||
public func value<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
public func value<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
||||||
|
|
||||||
return self.rawObject.value(forKey: property(O.meta).keyPath)! as! V
|
return self.rawObject.value(forKey: property(O.meta).keyPath)! as! V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the property of the receiver specified by a given key to a given value.
|
||||||
|
*/
|
||||||
public func setValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
public func setValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
||||||
|
|
||||||
self.rawObject.setValue(
|
self.rawObject.setValue(
|
||||||
@@ -119,11 +160,21 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the specified property from the managed object’s private internal storage.
|
||||||
|
|
||||||
|
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||||
|
*/
|
||||||
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Required<V>) -> V {
|
||||||
|
|
||||||
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath)! as! V
|
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath)! as! V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets in the object's private internal storage the value of a given property.
|
||||||
|
|
||||||
|
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||||
|
*/
|
||||||
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
public func setPrimitiveValue<V>(_ value: V, for property: (O) -> TransformableContainer<O>.Required<V>) {
|
||||||
|
|
||||||
self.rawObject.setPrimitiveValue(
|
self.rawObject.setPrimitiveValue(
|
||||||
@@ -135,11 +186,17 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Transformable.Optional utilities
|
// MARK: Transformable.Optional utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the property identified by a given key.
|
||||||
|
*/
|
||||||
public func value<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
public func value<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
||||||
|
|
||||||
return self.rawObject.value(forKey: property(O.meta).keyPath) as! V?
|
return self.rawObject.value(forKey: property(O.meta).keyPath) as! V?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the property of the receiver specified by a given key to a given value.
|
||||||
|
*/
|
||||||
public func setValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
public func setValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
||||||
|
|
||||||
self.rawObject.setValue(
|
self.rawObject.setValue(
|
||||||
@@ -148,11 +205,21 @@ public struct PartialObject<O: CoreStoreObject> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value for the specified property from the managed object’s private internal storage.
|
||||||
|
|
||||||
|
This method does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily by subclasses that implement custom accessor methods that need direct access to the receiver’s private storage.
|
||||||
|
*/
|
||||||
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
public func primitiveValue<V>(for property: (O) -> TransformableContainer<O>.Optional<V>) -> V? {
|
||||||
|
|
||||||
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V?
|
return self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets in the object's private internal storage the value of a given property.
|
||||||
|
|
||||||
|
Sets in the receiver’s private internal storage the value of the property specified by key to value.
|
||||||
|
*/
|
||||||
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
public func setPrimitiveValue<V>(_ value: V?, for property: (O) -> TransformableContainer<O>.Optional<V>) {
|
||||||
|
|
||||||
self.rawObject.setPrimitiveValue(
|
self.rawObject.setPrimitiveValue(
|
||||||
|
|||||||
@@ -226,8 +226,6 @@ public final class SQLiteStore: LocalStorage {
|
|||||||
*/
|
*/
|
||||||
public func cs_eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
|
public func cs_eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
|
||||||
|
|
||||||
// TODO: check if attached to persistent store
|
|
||||||
|
|
||||||
func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws {
|
func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws {
|
||||||
|
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ public extension DynamicObject where Self: CoreStoreObject {
|
|||||||
The containing type for transformable properties. `Transformable` properties support types that conforms to `NSCoding & NSCopying`.
|
The containing type for transformable properties. `Transformable` properties support types that conforms to `NSCoding & NSCopying`.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- Important: `Transformable` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
|
- Important: `Transformable` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties.
|
||||||
@@ -52,7 +52,7 @@ public extension DynamicObject where Self: CoreStoreObject {
|
|||||||
The containing type for transformable properties. Use the `DynamicObject.Transformable` typealias instead for shorter syntax.
|
The containing type for transformable properties. Use the `DynamicObject.Transformable` typealias instead for shorter syntax.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
The containing type for transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported.
|
The containing type for transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
Initializes the metadata for the property.
|
Initializes the metadata for the property.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let color = Transformable.Required<UIColor>(
|
let color = Transformable.Required<UIColor>(
|
||||||
"color",
|
"color",
|
||||||
initial: UIColor.clear,
|
initial: UIColor.clear,
|
||||||
@@ -292,7 +292,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
The containing type for optional transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported.
|
The containing type for optional transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
Initializes the metadata for the property.
|
Initializes the metadata for the property.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let color = Transformable.Optional<UIColor>(
|
let color = Transformable.Optional<UIColor>(
|
||||||
"color",
|
"color",
|
||||||
isTransient: true,
|
isTransient: true,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public extension DynamicObject where Self: CoreStoreObject {
|
|||||||
The containing type for value propertiess. `Value` properties support any type that conforms to `ImportableAttributeType`.
|
The containing type for value propertiess. `Value` properties support any type that conforms to `ImportableAttributeType`.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ public extension DynamicObject where Self: CoreStoreObject {
|
|||||||
The containing type for value properties. Use the `DynamicObject.Value` typealias instead for shorter syntax.
|
The containing type for value properties. Use the `DynamicObject.Value` typealias instead for shorter syntax.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
The containing type for required value properties. Any type that conforms to `ImportableAttributeType` are supported.
|
The containing type for required value properties. Any type that conforms to `ImportableAttributeType` are supported.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
@@ -80,9 +80,10 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
```
|
```
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let title = Value.Required<String>("title", initial: "Mr.")
|
let title = Value.Required<String>("title", initial: "Mr.")
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let displayName = Value.Required<String>(
|
let displayName = Value.Required<String>(
|
||||||
"displayName",
|
"displayName",
|
||||||
|
initial: "",
|
||||||
isTransient: true,
|
isTransient: true,
|
||||||
customGetter: Person.getName(_:)
|
customGetter: Person.getName(_:)
|
||||||
)
|
)
|
||||||
@@ -289,7 +290,7 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
The containing type for optional value properties. Any type that conforms to `ImportableAttributeType` are supported.
|
The containing type for optional value properties. Any type that conforms to `ImportableAttributeType` are supported.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let color = Transformable.Optional<UIColor>("color")
|
let color = Transformable.Optional<UIColor>("color")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ import Foundation
|
|||||||
The `VersionLock` contains the version hashes for entities. This is then passed to the `CoreStoreSchema`, which contains all entities for the store. An assertion will be raised if any `Entity` doesn't match the version hash.
|
The `VersionLock` contains the version hashes for entities. This is then passed to the `CoreStoreSchema`, which contains all entities for the store. An assertion will be raised if any `Entity` doesn't match the version hash.
|
||||||
```
|
```
|
||||||
class Animal: CoreStoreObject {
|
class Animal: CoreStoreObject {
|
||||||
let species = Value.Required<String>("species")
|
let species = Value.Required<String>("species", initial: "")
|
||||||
let nickname = Value.Optional<String>("nickname")
|
let nickname = Value.Optional<String>("nickname")
|
||||||
let master = Relationship.ToOne<Person>("master")
|
let master = Relationship.ToOne<Person>("master")
|
||||||
}
|
}
|
||||||
class Person: CoreStoreObject {
|
class Person: CoreStoreObject {
|
||||||
let name = Value.Required<String>("name")
|
let name = Value.Required<String>("name", initial: "")
|
||||||
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
let pet = Relationship.ToOne<Animal>("pet", inverse: { $0.master })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user