From 7f9a915d7178b96731ecb829e8f678a787e68f80 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Wed, 7 Jun 2017 20:07:43 +0900 Subject: [PATCH 01/17] WIP: Swift 3.2 --- Sources/AsynchronousDataTransaction.swift | 10 ++-- Sources/BaseDataTransaction+Querying.swift | 32 ++++++------ Sources/BaseDataTransaction.swift | 4 +- Sources/CSSelect.swift | 2 +- Sources/CSSetupResult.swift | 2 +- Sources/ClauseTypes.swift | 6 +-- ...reStore+CustomDebugStringConvertible.swift | 2 + Sources/CoreStore+Migration.swift | 2 +- Sources/CoreStore+Observing.swift | 18 +++---- Sources/CoreStore+Querying.swift | 28 +++++----- Sources/CoreStoreFetchRequest+CoreStore.swift | 2 +- .../CoreStoreFetchedResultsController.swift | 6 +-- Sources/CoreStoreObject+Querying.swift | 22 ++++---- Sources/DataStack+Migration.swift | 2 +- Sources/DataStack+Observing.swift | 18 +++---- Sources/DataStack+Querying.swift | 28 +++++----- Sources/DataStack+Transaction.swift | 6 +-- Sources/FetchableSource.swift | 20 ++++---- Sources/From.swift | 4 +- Sources/GroupBy.swift | 2 +- Sources/ImportableUniqueObject.swift | 51 ++++++++----------- Sources/Into.swift | 2 +- Sources/ListMonitor.swift | 4 +- Sources/MigrationChain.swift | 2 +- Sources/NSManagedObjectContext+Querying.swift | 32 ++++++------ Sources/ObjectMonitor.swift | 4 +- Sources/OrderBy.swift | 2 +- Sources/QueryableAttributeType.swift | 12 ++++- Sources/QueryableSource.swift | 8 +-- Sources/Relationship.swift | 18 +++---- Sources/Select.swift | 2 +- Sources/SetupResult.swift | 2 +- Sources/SynchronousDataTransaction.swift | 10 ++-- Sources/Tweak.swift | 2 +- Sources/UnsafeDataTransaction+Observing.swift | 18 +++---- Sources/Value.swift | 12 ++--- Sources/Where.swift | 2 +- 37 files changed, 199 insertions(+), 200 deletions(-) diff --git a/Sources/AsynchronousDataTransaction.swift b/Sources/AsynchronousDataTransaction.swift index 08caeab..d31380b 100644 --- a/Sources/AsynchronousDataTransaction.swift +++ b/Sources/AsynchronousDataTransaction.swift @@ -100,7 +100,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { - parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration - returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type. */ - public override func create(_ into: Into) -> T { + public override func create(_ into: Into) -> T { CoreStore.assert( !self.isCommitted, @@ -133,7 +133,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { - parameter objectID: the `NSManagedObjectID` for the object to be edited - returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`. */ - public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { + public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { CoreStore.assert( !self.isCommitted, @@ -266,9 +266,9 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { } switch childTransaction.result { - case nil: return nil - case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges) - case (_, let error?)?: return SaveResult(error) + case .none: return nil + case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges) + case .some(_, let error?): return SaveResult(error) } } } diff --git a/Sources/BaseDataTransaction+Querying.swift b/Sources/BaseDataTransaction+Querying.swift index 4fa9893..776507f 100644 --- a/Sources/BaseDataTransaction+Querying.swift +++ b/Sources/BaseDataTransaction+Querying.swift @@ -39,7 +39,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - returns: the number of `DynamicObject`s deleted */ @discardableResult - public func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? { + public func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -57,7 +57,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - returns: the number of `DynamicObject`s deleted */ @discardableResult - public func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? { + public func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -121,7 +121,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -137,7 +137,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -153,7 +153,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -169,7 +169,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -185,7 +185,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -201,7 +201,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -217,7 +217,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -233,7 +233,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -249,7 +249,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -265,7 +265,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -287,7 +287,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -306,7 +306,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -325,7 +325,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -344,7 +344,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { CoreStore.assert( self.isRunningInAllowedQueue(), diff --git a/Sources/BaseDataTransaction.swift b/Sources/BaseDataTransaction.swift index dd04b78..3a657f7 100644 --- a/Sources/BaseDataTransaction.swift +++ b/Sources/BaseDataTransaction.swift @@ -50,7 +50,7 @@ public /*abstract*/ class BaseDataTransaction { - parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration - returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type. */ - public func create(_ into: Into) -> T { + public func create(_ into: Into) -> T { let entityClass = into.entityClass CoreStore.assert( @@ -141,7 +141,7 @@ public /*abstract*/ class BaseDataTransaction { - parameter objectID: the `NSManagedObjectID` for the object to be edited - returns: an editable proxy for the specified `NSManagedObject`. */ - public func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { + public func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { CoreStore.assert( self.isRunningInAllowedQueue(), diff --git a/Sources/CSSelect.swift b/Sources/CSSelect.swift index 74fa947..09f1799 100644 --- a/Sources/CSSelect.swift +++ b/Sources/CSSelect.swift @@ -365,7 +365,7 @@ public final class CSSelect: NSObject { super.init() } - public init(_ swiftValue: Select) { + public init(_ swiftValue: Select) { self.attributeType = .undefinedAttributeType self.selectTerms = swiftValue.selectTerms diff --git a/Sources/CSSetupResult.swift b/Sources/CSSetupResult.swift index 124b255..2171945 100644 --- a/Sources/CSSetupResult.swift +++ b/Sources/CSSetupResult.swift @@ -152,7 +152,7 @@ public final class CSSetupResult: NSObject { // MARK: CoreStoreObjectiveCType - public required init(_ swiftValue: SetupResult) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface { + public required init(_ swiftValue: SetupResult) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface { switch swiftValue { diff --git a/Sources/ClauseTypes.swift b/Sources/ClauseTypes.swift index df207bb..b03f3e2 100644 --- a/Sources/ClauseTypes.swift +++ b/Sources/ClauseTypes.swift @@ -34,7 +34,7 @@ import CoreData */ public protocol FetchClause { - func applyToFetchRequest(_ fetchRequest: NSFetchRequest) + func applyToFetchRequest(_ fetchRequest: NSFetchRequest) } @@ -45,7 +45,7 @@ public protocol FetchClause { */ public protocol QueryClause { - func applyToFetchRequest(_ fetchRequest: NSFetchRequest) + func applyToFetchRequest(_ fetchRequest: NSFetchRequest) } @@ -56,5 +56,5 @@ public protocol QueryClause { */ public protocol DeleteClause { - func applyToFetchRequest(_ fetchRequest: NSFetchRequest) + func applyToFetchRequest(_ fetchRequest: NSFetchRequest) } diff --git a/Sources/CoreStore+CustomDebugStringConvertible.swift b/Sources/CoreStore+CustomDebugStringConvertible.swift index dc197e3..51038aa 100644 --- a/Sources/CoreStore+CustomDebugStringConvertible.swift +++ b/Sources/CoreStore+CustomDebugStringConvertible.swift @@ -1214,6 +1214,8 @@ extension NSAttributeType: CoreStoreDebugStringConvertible { case .binaryDataAttributeType: return ".binaryDataAttributeType" case .transformableAttributeType: return ".transformableAttributeType" case .objectIDAttributeType: return ".objectIDAttributeType" + case .UUIDAttributeType: return ".UUIDAttributeType" + case .URIAttributeType: return ".URIAttributeType" } } } diff --git a/Sources/CoreStore+Migration.swift b/Sources/CoreStore+Migration.swift index 8f16239..f93d6c9 100644 --- a/Sources/CoreStore+Migration.swift +++ b/Sources/CoreStore+Migration.swift @@ -47,7 +47,7 @@ public extension CoreStore { - parameter storage: the storage - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration. */ - public static func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) { + public static func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) { self.defaultStack.addStorage(storage, completion: completion) } diff --git a/Sources/CoreStore+Observing.swift b/Sources/CoreStore+Observing.swift index 53828fd..d5e543b 100644 --- a/Sources/CoreStore+Observing.swift +++ b/Sources/CoreStore+Observing.swift @@ -38,7 +38,7 @@ public extension CoreStore { - parameter object: the `DynamicObject` to observe changes from - returns: a `ObjectMonitor` that monitors changes to `object` */ - public static func monitorObject(_ object: T) -> ObjectMonitor { + public static func monitorObject(_ object: T) -> ObjectMonitor { return self.defaultStack.monitorObject(object) } @@ -50,7 +50,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public static func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { + public static func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { return self.defaultStack.monitorList(from, fetchClauses) } @@ -62,7 +62,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public static func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { + public static func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { return self.defaultStack.monitorList(from, fetchClauses) } @@ -74,7 +74,7 @@ public extension CoreStore { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { + public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses) } @@ -86,7 +86,7 @@ public extension CoreStore { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { + public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses) } @@ -99,7 +99,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { + public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses) } @@ -112,7 +112,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { + public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses) } @@ -125,7 +125,7 @@ public extension CoreStore { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { + public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) } @@ -138,7 +138,7 @@ public extension CoreStore { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { + public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) } diff --git a/Sources/CoreStore+Querying.swift b/Sources/CoreStore+Querying.swift index 67e7812..48cf117 100644 --- a/Sources/CoreStore+Querying.swift +++ b/Sources/CoreStore+Querying.swift @@ -82,7 +82,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public static func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { + public static func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { return self.defaultStack.fetchOne(from, fetchClauses) } @@ -94,7 +94,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public static func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { + public static func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { return self.defaultStack.fetchOne(from, fetchClauses) } @@ -106,7 +106,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public static func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { + public static func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { return self.defaultStack.fetchAll(from, fetchClauses) } @@ -118,7 +118,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public static func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { + public static func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { return self.defaultStack.fetchAll(from, fetchClauses) } @@ -130,7 +130,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public static func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { + public static func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { return self.defaultStack.fetchCount(from, fetchClauses) } @@ -142,7 +142,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public static func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { + public static func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { return self.defaultStack.fetchCount(from, fetchClauses) } @@ -154,7 +154,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public static func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { + public static func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { return self.defaultStack.fetchObjectID(from, fetchClauses) } @@ -166,7 +166,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public static func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { + public static func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { return self.defaultStack.fetchObjectID(from, fetchClauses) } @@ -178,7 +178,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public static func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { + public static func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { return self.defaultStack.fetchObjectIDs(from, fetchClauses) } @@ -190,7 +190,7 @@ public extension CoreStore { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public static func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { + public static func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { return self.defaultStack.fetchObjectIDs(from, fetchClauses) } @@ -205,7 +205,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { return self.defaultStack.queryValue(from, selectClause, queryClauses) } @@ -220,7 +220,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { return self.defaultStack.queryValue(from, selectClause, queryClauses) } @@ -235,7 +235,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { + public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { return self.defaultStack.queryAttributes(from, selectClause, queryClauses) } @@ -250,7 +250,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { + public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { return self.defaultStack.queryAttributes(from, selectClause, queryClauses) } diff --git a/Sources/CoreStoreFetchRequest+CoreStore.swift b/Sources/CoreStoreFetchRequest+CoreStore.swift index cd2c3fb..735b6c6 100644 --- a/Sources/CoreStoreFetchRequest+CoreStore.swift +++ b/Sources/CoreStoreFetchRequest+CoreStore.swift @@ -34,7 +34,7 @@ internal extension CoreStoreFetchRequest { // MARK: Internal @nonobjc @inline(__always) - internal func dynamicCast() -> NSFetchRequest { + internal func dynamicCast() -> NSFetchRequest { return unsafeBitCast(self, to: NSFetchRequest.self) } diff --git a/Sources/CoreStoreFetchedResultsController.swift b/Sources/CoreStoreFetchedResultsController.swift index a5802d3..6fe2cf3 100644 --- a/Sources/CoreStoreFetchedResultsController.swift +++ b/Sources/CoreStoreFetchedResultsController.swift @@ -35,7 +35,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll // MARK: Internal @nonobjc - internal convenience init(dataStack: DataStack, fetchRequest: NSFetchRequest, from: From, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) { + internal convenience init(dataStack: DataStack, fetchRequest: NSFetchRequest, from: From, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) { self.init( context: dataStack.mainContext, @@ -47,7 +47,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll } @nonobjc - internal init(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) { + internal init(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) { _ = from.applyToFetchRequest( fetchRequest, @@ -83,7 +83,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll } @nonobjc - internal func dynamicCast() -> NSFetchedResultsController { + internal func dynamicCast() -> NSFetchedResultsController { return unsafeBitCast(self, to: NSFetchedResultsController.self) } diff --git a/Sources/CoreStoreObject+Querying.swift b/Sources/CoreStoreObject+Querying.swift index 7896b9a..0a87043 100644 --- a/Sources/CoreStoreObject+Querying.swift +++ b/Sources/CoreStoreObject+Querying.swift @@ -37,7 +37,7 @@ public extension DynamicObject where Self: CoreStoreObject { let keyPath: String = Person.keyPath { $0.nickname } ``` */ - public static func keyPath(_ attribute: (Self) -> ValueContainer.Required) -> String { + public static func keyPath(_ attribute: (Self) -> ValueContainer.Required) -> String { return attribute(self.meta).keyPath } @@ -48,7 +48,7 @@ public extension DynamicObject where Self: CoreStoreObject { let keyPath: String = Person.keyPath { $0.nickname } ``` */ - public static func keyPath(_ attribute: (Self) -> ValueContainer.Optional) -> String { + public static func keyPath(_ attribute: (Self) -> ValueContainer.Optional) -> String { return attribute(self.meta).keyPath } @@ -59,7 +59,7 @@ public extension DynamicObject where Self: CoreStoreObject { let keyPath: String = Person.keyPath { $0.pets } ``` */ - public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToOne) -> String { + public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToOne) -> String { return relationship(self.meta).keyPath } @@ -70,7 +70,7 @@ public extension DynamicObject where Self: CoreStoreObject { let keyPath: String = Person.keyPath { $0.pets } ``` */ - public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToManyOrdered) -> String { + public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToManyOrdered) -> String { return relationship(self.meta).keyPath } @@ -81,7 +81,7 @@ public extension DynamicObject where Self: CoreStoreObject { let keyPath: String = Person.keyPath { $0.pets } ``` */ - public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToManyUnordered) -> String { + public static func keyPath(_ relationship: (Self) -> RelationshipContainer.ToManyUnordered) -> String { return relationship(self.meta).keyPath } @@ -103,7 +103,7 @@ public extension DynamicObject where Self: CoreStoreObject { let person = CoreStore.fetchAll(From(), Person.orderBy(ascending: { $0.age })) ``` */ - public static func orderBy(ascending attribute: (Self) -> ValueContainer.Required) -> OrderBy { + public static func orderBy(ascending attribute: (Self) -> ValueContainer.Required) -> OrderBy { return OrderBy(.ascending(attribute(self.meta).keyPath)) } @@ -114,7 +114,7 @@ public extension DynamicObject where Self: CoreStoreObject { let person = CoreStore.fetchAll(From(), Person.orderBy(ascending: { $0.age })) ``` */ - public static func orderBy(ascending attribute: (Self) -> ValueContainer.Optional) -> OrderBy { + public static func orderBy(ascending attribute: (Self) -> ValueContainer.Optional) -> OrderBy { return OrderBy(.ascending(attribute(self.meta).keyPath)) } @@ -125,7 +125,7 @@ public extension DynamicObject where Self: CoreStoreObject { let person = CoreStore.fetchAll(From(), Person.orderBy(descending: { $0.age })) ``` */ - public static func orderBy(descending attribute: (Self) -> ValueContainer.Required) -> OrderBy { + public static func orderBy(descending attribute: (Self) -> ValueContainer.Required) -> OrderBy { return OrderBy(.descending(attribute(self.meta).keyPath)) } @@ -136,7 +136,7 @@ public extension DynamicObject where Self: CoreStoreObject { let person = CoreStore.fetchAll(From(), Person.orderBy(descending: { $0.age })) ``` */ - public static func orderBy(descending attribute: (Self) -> ValueContainer.Optional) -> OrderBy { + public static func orderBy(descending attribute: (Self) -> ValueContainer.Optional) -> OrderBy { return OrderBy(.descending(attribute(self.meta).keyPath)) } @@ -145,13 +145,13 @@ public extension DynamicObject where Self: CoreStoreObject { // MARK: Deprecated @available(*, deprecated, renamed: "orderBy(ascending:)") - public static func ascending(_ attribute: (Self) -> ValueContainer.Optional) -> OrderBy { + public static func ascending(_ attribute: (Self) -> ValueContainer.Optional) -> OrderBy { return OrderBy(.ascending(attribute(self.meta).keyPath)) } @available(*, deprecated, renamed: "orderBy(descending:)") - public static func descending(_ attribute: (Self) -> ValueContainer.Optional) -> OrderBy { + public static func descending(_ attribute: (Self) -> ValueContainer.Optional) -> OrderBy { return OrderBy(.descending(attribute(self.meta).keyPath)) } diff --git a/Sources/DataStack+Migration.swift b/Sources/DataStack+Migration.swift index 8d22919..d129ed0 100644 --- a/Sources/DataStack+Migration.swift +++ b/Sources/DataStack+Migration.swift @@ -47,7 +47,7 @@ public extension DataStack { - parameter storage: the storage - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration. */ - public func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) { + public func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) { self.coordinator.performAsynchronously { diff --git a/Sources/DataStack+Observing.swift b/Sources/DataStack+Observing.swift index 2c5c2ee..e4dea00 100644 --- a/Sources/DataStack+Observing.swift +++ b/Sources/DataStack+Observing.swift @@ -38,7 +38,7 @@ public extension DataStack { - parameter object: the `DynamicObject` to observe changes from - returns: a `ObjectMonitor` that monitors changes to `object` */ - public func monitorObject(_ object: T) -> ObjectMonitor { + public func monitorObject(_ object: T) -> ObjectMonitor { CoreStore.assert( Thread.isMainThread, @@ -54,7 +54,7 @@ public extension DataStack { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { + public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { return self.monitorList(from, fetchClauses) } @@ -66,7 +66,7 @@ public extension DataStack { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { + public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { CoreStore.assert( Thread.isMainThread, @@ -95,7 +95,7 @@ public extension DataStack { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { + public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses) } @@ -107,7 +107,7 @@ public extension DataStack { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { + public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { CoreStore.assert( Thread.isMainThread, @@ -138,7 +138,7 @@ public extension DataStack { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { + public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { return self.monitorSectionedList(from, sectionBy, fetchClauses) } @@ -151,7 +151,7 @@ public extension DataStack { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { + public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { CoreStore.assert( Thread.isMainThread, @@ -182,7 +182,7 @@ public extension DataStack { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { + public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) } @@ -195,7 +195,7 @@ public extension DataStack { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { + public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { CoreStore.assert( Thread.isMainThread, diff --git a/Sources/DataStack+Querying.swift b/Sources/DataStack+Querying.swift index 94d06ac..e87b40d 100644 --- a/Sources/DataStack+Querying.swift +++ b/Sources/DataStack+Querying.swift @@ -84,7 +84,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { CoreStore.assert( Thread.isMainThread, @@ -100,7 +100,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { CoreStore.assert( Thread.isMainThread, @@ -116,7 +116,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { CoreStore.assert( Thread.isMainThread, @@ -132,7 +132,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { CoreStore.assert( Thread.isMainThread, @@ -148,7 +148,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { CoreStore.assert( Thread.isMainThread, @@ -164,7 +164,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { CoreStore.assert( Thread.isMainThread, @@ -180,7 +180,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { CoreStore.assert( Thread.isMainThread, @@ -196,7 +196,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { CoreStore.assert( Thread.isMainThread, @@ -212,7 +212,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { CoreStore.assert( Thread.isMainThread, @@ -228,7 +228,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { CoreStore.assert( Thread.isMainThread, @@ -250,7 +250,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { CoreStore.assert( Thread.isMainThread, @@ -269,7 +269,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { CoreStore.assert( Thread.isMainThread, @@ -288,7 +288,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { CoreStore.assert( Thread.isMainThread, @@ -307,7 +307,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { CoreStore.assert( Thread.isMainThread, diff --git a/Sources/DataStack+Transaction.swift b/Sources/DataStack+Transaction.swift index 52a09c7..d2ff361 100644 --- a/Sources/DataStack+Transaction.swift +++ b/Sources/DataStack+Transaction.swift @@ -211,9 +211,9 @@ public extension DataStack { } switch transaction.result { - case nil: return nil - case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges) - case (_, let error?)?: return SaveResult(error) + case .none: return nil + case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges) + case .some(_, let error?): return SaveResult(error) } } } diff --git a/Sources/FetchableSource.swift b/Sources/FetchableSource.swift index 5e0ac20..12f677a 100644 --- a/Sources/FetchableSource.swift +++ b/Sources/FetchableSource.swift @@ -73,7 +73,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? + func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? /** Fetches the first `DynamicObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -82,7 +82,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the first `DynamicObject` instance that satisfies the specified `FetchClause`s */ - func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? + func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? /** Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -91,7 +91,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? + func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? /** Fetches all `DynamicObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -100,7 +100,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: all `DynamicObject` instances that satisfy the specified `FetchClause`s */ - func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? + func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? /** Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -109,7 +109,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? + func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? /** Fetches the number of `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -118,7 +118,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the number `DynamicObject`s that satisfy the specified `FetchClause`s */ - func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? + func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? /** Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -127,7 +127,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? + func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? /** Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -136,7 +136,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchClause`s */ - func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? + func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? /** Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -145,7 +145,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? + func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? /** Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. @@ -154,7 +154,7 @@ public protocol FetchableSource: class { - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchClause`s */ - func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? + func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? /** The internal `NSManagedObjectContext` managed by this `FetchableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases. diff --git a/Sources/From.swift b/Sources/From.swift index 0ccb9eb..6a746fa 100644 --- a/Sources/From.swift +++ b/Sources/From.swift @@ -139,7 +139,7 @@ public struct From { self.findPersistentStores = findPersistentStores } - internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool { + internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool { fetchRequest.entity = context.parentStack!.entityDescription(for: EntityIdentifier(self.entityClass))! guard applyAffectedStores else { @@ -157,7 +157,7 @@ public struct From { return false } - internal func applyAffectedStoresForFetchedRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool { + internal func applyAffectedStoresForFetchedRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool { let stores = self.findPersistentStores(context) fetchRequest.affectedStores = stores diff --git a/Sources/GroupBy.swift b/Sources/GroupBy.swift index 842b713..880bda8 100644 --- a/Sources/GroupBy.swift +++ b/Sources/GroupBy.swift @@ -71,7 +71,7 @@ public struct GroupBy: QueryClause, Hashable { // MARK: QueryClause - public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { + public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { if let keyPaths = fetchRequest.propertiesToGroupBy as? [String], keyPaths != self.keyPaths { diff --git a/Sources/ImportableUniqueObject.swift b/Sources/ImportableUniqueObject.swift index 7ced67e..05dbbfd 100644 --- a/Sources/ImportableUniqueObject.swift +++ b/Sources/ImportableUniqueObject.swift @@ -55,11 +55,6 @@ import CoreData */ public protocol ImportableUniqueObject: ImportableObject { - /** - The data type for the import source. This is most commonly an json type, `NSDictionary`, or another external source such as `NSUserDefaults`. - */ - associatedtype ImportSource - /** The data type for the entity's unique ID attribute */ @@ -125,6 +120,26 @@ public protocol ImportableUniqueObject: ImportableObject { public extension ImportableUniqueObject { + var uniqueIDValue: UniqueIDType { + + get { + + return self.cs_toRaw().getValue( + forKvcKey: type(of: self).uniqueIDKeyPath, + didGetValue: { UniqueIDType.cs_fromImportableNativeType($0 as! UniqueIDType.ImportableNativeType)! } + ) + } + set { + + self.cs_toRaw() + .setValue( + newValue, + forKvcKey: type(of: self).uniqueIDKeyPath, + willSetValue: { ($0.cs_toImportableNativeType() as! CoreDataNativeType) } + ) + } + } + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return Self.shouldUpdate(from: source, in: transaction) @@ -173,29 +188,3 @@ public extension ImportableUniqueObject { try self.update(from: source, in: transaction) } } - - -// MARK: - ImportableUniqueObject (Default Implementations) - -public extension ImportableUniqueObject where Self: DynamicObject { - - var uniqueIDValue: UniqueIDType { - - get { - - return self.cs_toRaw().getValue( - forKvcKey: type(of: self).uniqueIDKeyPath, - didGetValue: { UniqueIDType.cs_fromImportableNativeType($0 as! UniqueIDType.ImportableNativeType)! } - ) - } - set { - - self.cs_toRaw() - .setValue( - newValue, - forKvcKey: type(of: self).uniqueIDKeyPath, - willSetValue: { ($0.cs_toImportableNativeType() as! CoreDataNativeType) } - ) - } - } -} diff --git a/Sources/Into.swift b/Sources/Into.swift index ec070d6..8730af9 100644 --- a/Sources/Into.swift +++ b/Sources/Into.swift @@ -103,7 +103,7 @@ public struct Into: Hashable { // MARK: Equatable - public static func == (lhs: Into, rhs: Into) -> Bool { + public static func == (lhs: Into, rhs: Into) -> Bool { return lhs.entityClass == rhs.entityClass && lhs.configuration == rhs.configuration diff --git a/Sources/ListMonitor.swift b/Sources/ListMonitor.swift index 39536f4..2be4277 100644 --- a/Sources/ListMonitor.swift +++ b/Sources/ListMonitor.swift @@ -600,7 +600,7 @@ public final class ListMonitor: Hashable { return lhs.fetchedResultsController === rhs.fetchedResultsController } - public static func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool { + public static func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool { return lhs.fetchedResultsController === rhs.fetchedResultsController } @@ -610,7 +610,7 @@ public final class ListMonitor: Hashable { return lhs.fetchedResultsController === rhs.fetchedResultsController } - public static func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool { + public static func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool { return lhs.fetchedResultsController === rhs.fetchedResultsController } diff --git a/Sources/MigrationChain.swift b/Sources/MigrationChain.swift index 790749c..3f46dd8 100644 --- a/Sources/MigrationChain.swift +++ b/Sources/MigrationChain.swift @@ -87,7 +87,7 @@ public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLitera /** Initializes the `MigrationChain` with a linear order of versions, which becomes the order of the `DataStack`'s progressive migrations. */ - public init(_ elements: T) where T.Iterator.Element == String, T.SubSequence.Iterator.Element == String, T.Index: Comparable { + public init(_ elements: T) where T.Iterator.Element == String { CoreStore.assert(Set(elements).count == Array(elements).count, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to duplicate version strings.") diff --git a/Sources/NSManagedObjectContext+Querying.swift b/Sources/NSManagedObjectContext+Querying.swift index 084e331..11e58e6 100644 --- a/Sources/NSManagedObjectContext+Querying.swift +++ b/Sources/NSManagedObjectContext+Querying.swift @@ -101,13 +101,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? { return self.fetchOne(from, fetchClauses) } @nonobjc - public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { + public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -124,13 +124,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? { return self.fetchAll(from, fetchClauses) } @nonobjc - public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { + public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -148,13 +148,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? { return self.fetchCount(from, fetchClauses) } @nonobjc - public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { + public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -168,13 +168,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { return self.fetchObjectID(from, fetchClauses) } @nonobjc - public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { + public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -191,13 +191,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { return self.fetchObjectIDs(from, fetchClauses) } @nonobjc - public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { + public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -244,13 +244,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { // MARK: QueryableSource @nonobjc - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { return self.queryValue(from, selectClause, queryClauses) } @nonobjc - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -269,13 +269,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { } @nonobjc - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { return self.queryAttributes(from, selectClause, queryClauses) } @nonobjc - public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { + public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -305,13 +305,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { // MARK: Deleting @nonobjc - internal func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? { + internal func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? { return self.deleteAll(from, deleteClauses) } @nonobjc - internal func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? { + internal func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) diff --git a/Sources/ObjectMonitor.swift b/Sources/ObjectMonitor.swift index e32a177..b2d8db1 100644 --- a/Sources/ObjectMonitor.swift +++ b/Sources/ObjectMonitor.swift @@ -132,7 +132,7 @@ public final class ObjectMonitor: Equatable { return lhs === rhs } - public static func == (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool { + public static func == (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool { return lhs.fetchedResultsController === rhs.fetchedResultsController } @@ -142,7 +142,7 @@ public final class ObjectMonitor: Equatable { return lhs === rhs } - public static func ~= (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool { + public static func ~= (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool { return lhs.fetchedResultsController === rhs.fetchedResultsController } diff --git a/Sources/OrderBy.swift b/Sources/OrderBy.swift index 692a8fe..e79fafa 100644 --- a/Sources/OrderBy.swift +++ b/Sources/OrderBy.swift @@ -143,7 +143,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable { // MARK: FetchClause, QueryClause, DeleteClause - public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { + public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { if let sortDescriptors = fetchRequest.sortDescriptors, sortDescriptors != self.sortDescriptors { diff --git a/Sources/QueryableAttributeType.swift b/Sources/QueryableAttributeType.swift index c0c5dba..974bd06 100644 --- a/Sources/QueryableAttributeType.swift +++ b/Sources/QueryableAttributeType.swift @@ -434,12 +434,20 @@ extension NSNull: QueryableAttributeType { public typealias QueryableNativeType = NSNull - public static let cs_rawAttributeType: NSAttributeType = .undefinedAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .undefinedAttributeType + } @nonobjc @inline(__always) public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { - return self.init() + @inline(__always) + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) } @nonobjc @inline(__always) diff --git a/Sources/QueryableSource.swift b/Sources/QueryableSource.swift index 303c63c..4b40a42 100644 --- a/Sources/QueryableSource.swift +++ b/Sources/QueryableSource.swift @@ -44,7 +44,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? + func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? /** Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. @@ -56,7 +56,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? + func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? /** Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. @@ -68,7 +68,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? + func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? /** Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. @@ -80,7 +80,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? + func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? /** The internal `NSManagedObjectContext` managed by this `QueryableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases. diff --git a/Sources/Relationship.swift b/Sources/Relationship.swift index 88606be..365ae93 100644 --- a/Sources/Relationship.swift +++ b/Sources/Relationship.swift @@ -860,7 +860,7 @@ extension RelationshipContainer.ToManyOrdered: RandomAccessCollection { public func makeIterator() -> Iterator { - let iterator = self.nativeValue.makeIterator() + var iterator = self.nativeValue.makeIterator() return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) }) } @@ -915,7 +915,7 @@ extension RelationshipContainer.ToManyUnordered: Sequence { public func makeIterator() -> Iterator { - let iterator = self.nativeValue.makeIterator() + var iterator = self.nativeValue.makeIterator() return AnyIterator({ iterator.next().flatMap({ D.cs_fromRaw(object: $0 as! NSManagedObject) }) }) } } @@ -953,7 +953,7 @@ extension RelationshipContainer.ToOne { dog.master.value = anotherDog.master.value ``` */ - public static func .= (_ relationship: RelationshipContainer.ToOne, _ relationship2: RelationshipContainer.ToOne) { + public static func .= (_ relationship: RelationshipContainer.ToOne, _ relationship2: RelationshipContainer.ToOne) { relationship.nativeValue = relationship2.nativeValue } @@ -998,7 +998,7 @@ extension RelationshipContainer.ToOne { if dog.master.value == person { ... } ``` */ - public static func .== (_ relationship: RelationshipContainer.ToOne, _ relationship2: RelationshipContainer.ToOne) -> Bool { + public static func .== (_ relationship: RelationshipContainer.ToOne, _ relationship2: RelationshipContainer.ToOne) -> Bool { return relationship.nativeValue == relationship2.nativeValue } @@ -1031,7 +1031,7 @@ extension RelationshipContainer.ToManyOrdered { person.pets.value = anotherPerson.pets.value ``` */ - public static func .= (_ relationship: RelationshipContainer.ToManyOrdered, _ relationship2: RelationshipContainer.ToManyOrdered) { + public static func .= (_ relationship: RelationshipContainer.ToManyOrdered, _ relationship2: RelationshipContainer.ToManyOrdered) { relationship.nativeValue = relationship2.nativeValue } @@ -1082,7 +1082,7 @@ extension RelationshipContainer.ToManyOrdered { if person.pets.value == anotherPerson.pets.value { ... } ``` */ - public static func .== (_ relationship: RelationshipContainer.ToManyOrdered, _ relationship2: RelationshipContainer.ToManyOrdered) -> Bool { + public static func .== (_ relationship: RelationshipContainer.ToManyOrdered, _ relationship2: RelationshipContainer.ToManyOrdered) -> Bool { return relationship.nativeValue == relationship2.nativeValue } @@ -1115,7 +1115,7 @@ extension RelationshipContainer.ToManyUnordered { person.pets.value = anotherPerson.pets.value ``` */ - public static func .= (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyUnordered) { + public static func .= (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyUnordered) { relationship.nativeValue = relationship2.nativeValue } @@ -1130,7 +1130,7 @@ extension RelationshipContainer.ToManyUnordered { person.pets.value = anotherPerson.pets.value ``` */ - public static func .= (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyOrdered) { + public static func .= (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyOrdered) { relationship.nativeValue = NSSet(set: relationship2.nativeValue.set) } @@ -1175,7 +1175,7 @@ extension RelationshipContainer.ToManyUnordered { if person.pets.value == anotherPerson.pets.value { ... } ``` */ - public static func .== (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyUnordered) -> Bool { + public static func .== (_ relationship: RelationshipContainer.ToManyUnordered, _ relationship2: RelationshipContainer.ToManyUnordered) -> Bool { return relationship.nativeValue.isEqual(relationship2.nativeValue) } diff --git a/Sources/Select.swift b/Sources/Select.swift index 6b2e8c4..468d5e5 100644 --- a/Sources/Select.swift +++ b/Sources/Select.swift @@ -339,7 +339,7 @@ public struct Select: Hashable { // MARK: Equatable - public static func == (lhs: Select, rhs: Select) -> Bool { + public static func == (lhs: Select, rhs: Select) -> Bool { return lhs.selectTerms == rhs.selectTerms } diff --git a/Sources/SetupResult.swift b/Sources/SetupResult.swift index 545412a..26be478 100644 --- a/Sources/SetupResult.swift +++ b/Sources/SetupResult.swift @@ -88,7 +88,7 @@ public enum SetupResult: Hashable { // MARK: Equatable - public static func == (lhs: SetupResult, rhs: SetupResult) -> Bool { + public static func == (lhs: SetupResult, rhs: SetupResult) -> Bool { switch (lhs, rhs) { diff --git a/Sources/SynchronousDataTransaction.swift b/Sources/SynchronousDataTransaction.swift index d9a3f92..0957a2d 100644 --- a/Sources/SynchronousDataTransaction.swift +++ b/Sources/SynchronousDataTransaction.swift @@ -55,7 +55,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction { - parameter into: the `Into` clause indicating the destination `NSManagedObject` or `CoreStoreObject` entity type and the destination configuration - returns: a new `NSManagedObject` or `CoreStoreObject` instance of the specified entity type. */ - public override func create(_ into: Into) -> T { + public override func create(_ into: Into) -> T { CoreStore.assert( !self.isCommitted, @@ -88,7 +88,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction { - parameter objectID: the `NSManagedObjectID` for the object to be edited - returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`. */ - public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { + public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? { CoreStore.assert( !self.isCommitted, @@ -230,9 +230,9 @@ public final class SynchronousDataTransaction: BaseDataTransaction { } switch childTransaction.result { - case nil: return nil - case (let hasChanges, nil)?: return SaveResult(hasChanges: hasChanges) - case (_, let error?)?: return SaveResult(error) + case .none: return nil + case .some(let hasChanges, nil): return SaveResult(hasChanges: hasChanges) + case .some(_, let error?): return SaveResult(error) } } } diff --git a/Sources/Tweak.swift b/Sources/Tweak.swift index 108be78..17e3b0a 100644 --- a/Sources/Tweak.swift +++ b/Sources/Tweak.swift @@ -63,7 +63,7 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause { // MARK: FetchClause, QueryClause, DeleteClause - public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { + public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { self.closure(fetchRequest as! NSFetchRequest) } diff --git a/Sources/UnsafeDataTransaction+Observing.swift b/Sources/UnsafeDataTransaction+Observing.swift index 3a85332..02cbd03 100644 --- a/Sources/UnsafeDataTransaction+Observing.swift +++ b/Sources/UnsafeDataTransaction+Observing.swift @@ -38,7 +38,7 @@ public extension UnsafeDataTransaction { - parameter object: the `DynamicObject` to observe changes from - returns: a `ObjectMonitor` that monitors changes to `object` */ - public func monitorObject(_ object: T) -> ObjectMonitor { + public func monitorObject(_ object: T) -> ObjectMonitor { return ObjectMonitor( unsafeTransaction: self, @@ -53,7 +53,7 @@ public extension UnsafeDataTransaction { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { + public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor { return self.monitorList(from, fetchClauses) } @@ -65,7 +65,7 @@ public extension UnsafeDataTransaction { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { + public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor { CoreStore.assert( fetchClauses.filter { $0 is OrderBy }.count > 0, @@ -90,7 +90,7 @@ public extension UnsafeDataTransaction { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { + public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) { self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses) } @@ -102,7 +102,7 @@ public extension UnsafeDataTransaction { - parameter from: a `From` clause indicating the entity type - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { + public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause]) { CoreStore.assert( fetchClauses.filter { $0 is OrderBy }.count > 0, @@ -129,7 +129,7 @@ public extension UnsafeDataTransaction { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { + public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { return self.monitorSectionedList(from, sectionBy, fetchClauses) } @@ -142,7 +142,7 @@ public extension UnsafeDataTransaction { - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - returns: a `ListMonitor` instance that monitors changes to the list */ - public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { + public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { CoreStore.assert( fetchClauses.filter { $0 is OrderBy }.count > 0, @@ -168,7 +168,7 @@ public extension UnsafeDataTransaction { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { + public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) } @@ -181,7 +181,7 @@ public extension UnsafeDataTransaction { - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. */ - public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { + public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { CoreStore.assert( fetchClauses.filter { $0 is OrderBy }.count > 0, diff --git a/Sources/Value.swift b/Sources/Value.swift index 17b9941..72f94ce 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -733,7 +733,7 @@ extension ValueContainer.Required { animal.species.value = anotherAnimal.species.value ``` */ - public static func .= (_ property: ValueContainer.Required, _ property2: ValueContainer.Required) { + public static func .= (_ property: ValueContainer.Required, _ property2: ValueContainer.Required) { property.value = property2.value } @@ -826,7 +826,7 @@ extension ValueContainer.Optional { animal.nickname.value = anotherAnimal.nickname.value ``` */ - public static func .= (_ property: ValueContainer.Optional, _ property2: ValueContainer.Optional) { + public static func .= (_ property: ValueContainer.Optional, _ property2: ValueContainer.Optional) { property.value = property2.value } @@ -841,7 +841,7 @@ extension ValueContainer.Optional { animal.nickname.value = anotherAnimal.species.value ``` */ - public static func .= (_ property: ValueContainer.Optional, _ property2: ValueContainer.Required) { + public static func .= (_ property: ValueContainer.Optional, _ property2: ValueContainer.Required) { property.value = property2.value } @@ -934,7 +934,7 @@ extension TransformableContainer.Required { animal.nickname.value = anotherAnimal.species.value ``` */ - public static func .= (_ property: TransformableContainer.Required, _ property2: TransformableContainer.Required) { + public static func .= (_ property: TransformableContainer.Required, _ property2: TransformableContainer.Required) { property.value = property2.value } @@ -967,7 +967,7 @@ extension TransformableContainer.Optional { animal.color.value = anotherAnimal.color.value ``` */ - public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Optional) { + public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Optional) { property.value = property2.value } @@ -982,7 +982,7 @@ extension TransformableContainer.Optional { animal.color.value = anotherAnimal.color.value ``` */ - public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Required) { + public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Required) { property.value = property2.value } diff --git a/Sources/Where.swift b/Sources/Where.swift index 2571238..76a095b 100644 --- a/Sources/Where.swift +++ b/Sources/Where.swift @@ -187,7 +187,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { // MARK: FetchClause, QueryClause, DeleteClause - public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { + public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { if let predicate = fetchRequest.predicate, predicate != self.predicate { From f618617053613f9be464dc46e778636f4538c626 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Thu, 8 Jun 2017 20:18:50 +0900 Subject: [PATCH 02/17] work around issue that crashes the Swift 3.2 compiler (fixes #171) --- .../ObjectObserverDemoViewController.swift | 2 +- .../Palette.swift | 2 +- .../TransactionsDemoViewController.swift | 2 +- CoreStoreTests/ImportTests.swift | 48 +-- CoreStoreTests/ListObserverTests.swift | 156 ++++--- CoreStoreTests/ObjectObserverTests.swift | 2 +- README.md | 2 +- Sources/CSGroupBy.swift | 6 +- Sources/CSSectionBy.swift | 4 +- Sources/CSSelect.swift | 14 +- Sources/CSWhere.swift | 4 +- Sources/CoreStoreBridge.h | 2 +- Sources/CoreStoreManagedObject.swift | 4 +- Sources/CoreStoreSchema.swift | 2 +- Sources/CustomSchemaMappingProvider.swift | 16 +- Sources/DataStack+Transaction.swift | 8 +- Sources/DynamicSchema+Convenience.swift | 20 +- Sources/GroupBy.swift | 6 +- Sources/ImportableAttributeType.swift | 381 +----------------- Sources/ImportableUniqueObject.swift | 11 +- Sources/ListMonitor.swift | 2 +- .../NSEntityDescription+DynamicModel.swift | 4 +- Sources/NSManagedObject+Convenience.swift | 20 +- Sources/NSManagedObject+ObjectiveC.swift | 4 +- Sources/ObjectObserver.swift | 4 +- Sources/OrderBy.swift | 12 +- Sources/QueryableAttributeType.swift | 46 ++- Sources/Relationship.swift | 44 +- Sources/SectionBy.swift | 6 +- Sources/Select.swift | 26 +- Sources/Value.swift | 32 +- Sources/Where.swift | 10 +- 32 files changed, 280 insertions(+), 622 deletions(-) diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift index ce95fe4..5f315fb 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift @@ -85,7 +85,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { // MARK: ObjectObserver - func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Palette, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Palette, changedPersistentKeys: Set) { self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys) } diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift index fffc643..a689de5 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift @@ -49,7 +49,7 @@ class Palette: NSManagedObject { } set { - self.setValue(newValue.cs_toImportableNativeType(), forKvcKey: #keyPath(Palette.colorName)) + self.setValue(newValue.cs_toQueryableNativeType(), forKvcKey: #keyPath(Palette.colorName)) } } diff --git a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift index 254c96e..5662123 100644 --- a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift @@ -131,7 +131,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec // none } - func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Place, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Place, changedPersistentKeys: Set) { if let mapView = self.mapView { diff --git a/CoreStoreTests/ImportTests.swift b/CoreStoreTests/ImportTests.swift index f2e221e..b248a10 100644 --- a/CoreStoreTests/ImportTests.swift +++ b/CoreStoreTests/ImportTests.swift @@ -36,33 +36,33 @@ class ImportTests: BaseTestDataTestCase { @objc dynamic func test_ThatAttributeProtocols_BehaveCorrectly() { - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: true))?.boolValue, true) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT)) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: true))?.boolValue, true) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max))?.int16Value, Int16.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max))?.int32Value, Int32.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max))?.int64Value, Int64.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT))?.floatValue, MAXFLOAT) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT)))?.doubleValue, Double(MAXFLOAT)) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue) - XCTAssertEqual(NSDecimalNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue) + XCTAssertEqual(NSDecimalNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue) - XCTAssertEqual(NSNumber.cs_fromImportableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: "1"))?.boolValue, true) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int16.max.description))?.int16Value, Int16.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int32.max.description))?.int32Value, Int32.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: Int64.max.description))?.int64Value, Int64.max) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.doubleValue, NSDecimalNumber(string: MAXFLOAT.description).doubleValue) + XCTAssertEqual(NSNumber.cs_fromQueryableNativeType(NSDecimalNumber(string: MAXFLOAT.description))?.floatValue, NSDecimalNumber(string: MAXFLOAT.description).floatValue) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: true))) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int16.max))) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int32.max))) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Int64.max))) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: MAXFLOAT))) - XCTAssertNil(NSDecimalNumber.cs_fromImportableNativeType(NSNumber(value: Double(MAXFLOAT)))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: true))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int16.max))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int32.max))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Int64.max))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: MAXFLOAT))) + XCTAssertNil(NSDecimalNumber.cs_fromQueryableNativeType(NSNumber(value: Double(MAXFLOAT)))) XCTAssertEqual(true.cs_toQueryableNativeType(), NSNumber(value: true)) XCTAssertEqual(Int16.max.cs_toQueryableNativeType(), NSNumber(value: Int16.max)) diff --git a/CoreStoreTests/ListObserverTests.swift b/CoreStoreTests/ListObserverTests.swift index 5b1d68f..7e40beb 100644 --- a/CoreStoreTests/ListObserverTests.swift +++ b/CoreStoreTests/ListObserverTests.swift @@ -198,60 +198,58 @@ class ListObserverTests: BaseTestDataTestCase { return events == 0 } ) - for _ in 1 ... 2 { - - let didUpdateObjectExpectation = self.expectation( - forNotification: "listMonitor:didUpdateObject:atIndexPath:", - object: observer, - handler: { (note) -> Bool in + + let didUpdateObjectExpectation = self.expectation( + forNotification: "listMonitor:didUpdateObject:atIndexPath:", + object: observer, + handler: { (note) -> Bool in + + XCTAssert(events == 1 || events == 2) + + let userInfo = note.userInfo + XCTAssertNotNil(userInfo) + XCTAssertEqual( + Set(userInfo?.keys.map({ $0 as! String }) ?? []), + ["indexPath", "object"] + ) + + let indexPath = userInfo?["indexPath"] as? NSIndexPath + let object = userInfo?["object"] as? TestEntity1 + + switch object?.testEntityID { - XCTAssert(events == 1 || events == 2) + case NSNumber(value: 101)?: + XCTAssertEqual(indexPath?.index(atPosition: 0), 1) + XCTAssertEqual(indexPath?.index(atPosition: 1), 0) - let userInfo = note.userInfo - XCTAssertNotNil(userInfo) - XCTAssertEqual( - Set(userInfo?.keys.map({ $0 as! String }) ?? []), - ["indexPath", "object"] - ) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 11)) + XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11")) + XCTAssertEqual(object?.testString, "nil:TestEntity1:11") + XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!) - let indexPath = userInfo?["indexPath"] as? NSIndexPath - let object = userInfo?["object"] as? TestEntity1 + case NSNumber(value: 102)?: + XCTAssertEqual(indexPath?.index(atPosition: 0), 0) + XCTAssertEqual(indexPath?.index(atPosition: 1), 0) - switch object?.testEntityID { - - case NSNumber(value: 101)?: - XCTAssertEqual(indexPath?.index(atPosition: 0), 1) - XCTAssertEqual(indexPath?.index(atPosition: 1), 0) - - XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) - XCTAssertEqual(object?.testNumber, NSNumber(value: 11)) - XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11")) - XCTAssertEqual(object?.testString, "nil:TestEntity1:11") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!) - - case NSNumber(value: 102)?: - XCTAssertEqual(indexPath?.index(atPosition: 0), 0) - XCTAssertEqual(indexPath?.index(atPosition: 1), 0) - - XCTAssertEqual(object?.testBoolean, NSNumber(value: false)) - XCTAssertEqual(object?.testNumber, NSNumber(value: 22)) - XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22")) - XCTAssertEqual(object?.testString, "nil:TestEntity1:22") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!) - - default: - XCTFail() - } - defer { - - events += 1 - } - return events == 1 || events == 2 + XCTAssertEqual(object?.testBoolean, NSNumber(value: false)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 22)) + XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22")) + XCTAssertEqual(object?.testString, "nil:TestEntity1:22") + XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!) + + default: + XCTFail() } - ) - } + defer { + + events += 1 + } + return events == 1 || events == 2 + } + ) let didChangeExpectation = self.expectation( forNotification: "listMonitorDidChange:", object: observer, @@ -453,38 +451,35 @@ class ListObserverTests: BaseTestDataTestCase { return events == 0 } ) - for _ in 1 ... 2 { - - let didUpdateObjectExpectation = self.expectation( - forNotification: "listMonitor:didDeleteObject:fromIndexPath:", - object: observer, - handler: { (note) -> Bool in + let didUpdateObjectExpectation = self.expectation( + forNotification: "listMonitor:didDeleteObject:fromIndexPath:", + object: observer, + handler: { (note) -> Bool in + + XCTAssert(events == 1 || events == 2) + + let userInfo = note.userInfo + XCTAssertNotNil(userInfo) + XCTAssertEqual( + Set(userInfo?.keys.map({ $0 as! String }) ?? []), + ["indexPath", "object"] + ) + + let indexPath = userInfo?["indexPath"] as? NSIndexPath + + XCTAssertEqual(indexPath?.section, 0) + XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1) + + let object = userInfo?["object"] as? TestEntity1 + XCTAssertEqual(object?.isDeleted, true) + + defer { - XCTAssert(events == 1 || events == 2) - - let userInfo = note.userInfo - XCTAssertNotNil(userInfo) - XCTAssertEqual( - Set(userInfo?.keys.map({ $0 as! String }) ?? []), - ["indexPath", "object"] - ) - - let indexPath = userInfo?["indexPath"] as? NSIndexPath - - XCTAssertEqual(indexPath?.section, 0) - XCTAssert(indexPath?.index(atPosition: 1) == 0 || indexPath?.index(atPosition: 1) == 1) - - let object = userInfo?["object"] as? TestEntity1 - XCTAssertEqual(object?.isDeleted, true) - - defer { - - events += 1 - } - return events == 1 || events == 2 + events += 1 } - ) - } + return events == 1 || events == 2 + } + ) let didDeleteSectionExpectation = self.expectation( forNotification: "listMonitor:didDeleteSection:fromSectionIndex:", object: observer, @@ -531,10 +526,11 @@ class ListObserverTests: BaseTestDataTestCase { stack.perform( asynchronous: { (transaction) -> Bool in - transaction.deleteAll( + let count = transaction.deleteAll( From(), Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false) ) + XCTAssertEqual(count, 2) return transaction.hasChanges }, success: { (hasChanges) in diff --git a/CoreStoreTests/ObjectObserverTests.swift b/CoreStoreTests/ObjectObserverTests.swift index 0b6c3d0..bc62132 100644 --- a/CoreStoreTests/ObjectObserverTests.swift +++ b/CoreStoreTests/ObjectObserverTests.swift @@ -219,7 +219,7 @@ class TestObjectObserver: ObjectObserver { ) } - func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: TestEntity1, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: TestEntity1, changedPersistentKeys: Set) { NotificationCenter.default.post( name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"), diff --git a/README.md b/README.md index 83203bc..d097cff 100644 --- a/README.md +++ b/README.md @@ -1446,7 +1446,7 @@ class MyViewController: UIViewController, ObjectObserver { // ... } - func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: MyPersonEntity, changedPersistentKeys: Set) { + func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: MyPersonEntity, changedPersistentKeys: Set) { // ... } diff --git a/Sources/CSGroupBy.swift b/Sources/CSGroupBy.swift index 27c331d..189f0a4 100644 --- a/Sources/CSGroupBy.swift +++ b/Sources/CSGroupBy.swift @@ -41,7 +41,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { The list of key path strings to group results with */ @objc - public var keyPaths: [KeyPath] { + public var keyPaths: [RawKeyPath] { return self.bridgeToSwift.keyPaths } @@ -52,7 +52,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { - parameter keyPath: a key path string to group results with */ @objc - public convenience init(keyPath: KeyPath) { + public convenience init(keyPath: RawKeyPath) { self.init(GroupBy(keyPath)) } @@ -63,7 +63,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { - parameter keyPaths: a list of key path strings to group results with */ @objc - public convenience init(keyPaths: [KeyPath]) { + public convenience init(keyPaths: [RawKeyPath]) { self.init(GroupBy(keyPaths)) } diff --git a/Sources/CSSectionBy.swift b/Sources/CSSectionBy.swift index 6533fa0..ba0a93c 100644 --- a/Sources/CSSectionBy.swift +++ b/Sources/CSSectionBy.swift @@ -45,7 +45,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType { - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections */ @objc - public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy { + public static func keyPath(_ sectionKeyPath: RawKeyPath) -> CSSectionBy { return self.init(SectionBy(sectionKeyPath)) } @@ -58,7 +58,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType { - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections */ @objc - public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy { + public static func keyPath(_ sectionKeyPath: RawKeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy { return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer)) } diff --git a/Sources/CSSelect.swift b/Sources/CSSelect.swift index 09f1799..d755766 100644 --- a/Sources/CSSelect.swift +++ b/Sources/CSSelect.swift @@ -48,7 +48,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - parameter keyPath: the attribute name */ @objc - public convenience init(keyPath: KeyPath) { + public convenience init(keyPath: RawKeyPath) { self.init(.attribute(keyPath)) } @@ -65,7 +65,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute */ @objc - public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { + public static func average(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm { return self.init(.average(keyPath, as: alias)) } @@ -82,7 +82,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `SelectTerm` to a `Select` clause for a count query */ @objc - public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { + public static func count(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm { return self.init(.count(keyPath, as: alias)) } @@ -99,7 +99,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute */ @objc - public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { + public static func maximum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm { return self.init(.maximum(keyPath, as: alias)) } @@ -116,7 +116,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute */ @objc - public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { + public static func minimum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm { return self.init(.minimum(keyPath, as: alias)) } @@ -133,7 +133,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute */ @objc - public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { + public static func sum(_ keyPath: RawKeyPath, as alias: RawKeyPath?) -> CSSelectTerm { return self.init(.sum(keyPath, as: alias)) } @@ -150,7 +150,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute */ @objc - public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm { + public static func objectIDAs(_ alias: RawKeyPath? = nil) -> CSSelectTerm { return self.init(.objectID(as: alias)) } diff --git a/Sources/CSWhere.swift b/Sources/CSWhere.swift index 50813d7..5949990 100644 --- a/Sources/CSWhere.swift +++ b/Sources/CSWhere.swift @@ -85,7 +85,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau - parameter value: the arguments for the `==` operator */ @objc - public convenience init(keyPath: KeyPath, isEqualTo value: CoreDataNativeType?) { + public convenience init(keyPath: RawKeyPath, isEqualTo value: CoreDataNativeType?) { self.init(value == nil || value is NSNull ? Where("\(keyPath) == nil") @@ -99,7 +99,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau - parameter list: the array to check membership of */ @objc - public convenience init(keyPath: KeyPath, isMemberOf list: [CoreDataNativeType]) { + public convenience init(keyPath: RawKeyPath, isMemberOf list: [CoreDataNativeType]) { self.init(Where("\(keyPath) IN %@", list as NSArray)) } diff --git a/Sources/CoreStoreBridge.h b/Sources/CoreStoreBridge.h index 9af4fe2..407258d 100644 --- a/Sources/CoreStoreBridge.h +++ b/Sources/CoreStoreBridge.h @@ -43,7 +43,7 @@ #define CORESTORE_RETURNS_RETAINED __attribute__((ns_returns_retained)) -#pragma mark - KeyPath Utilities +#pragma mark - RawKeyPath Utilities #define CSKeyPath(type, property) ({ \ type *_je_keypath_dummy __attribute__((unused)); \ diff --git a/Sources/CoreStoreManagedObject.swift b/Sources/CoreStoreManagedObject.swift index f3c3b6c..76d174b 100644 --- a/Sources/CoreStoreManagedObject.swift +++ b/Sources/CoreStoreManagedObject.swift @@ -14,7 +14,7 @@ import CoreData @objc internal class CoreStoreManagedObject: NSManagedObject { @nonobjc - internal class func cs_setKeyPathsForValuesAffectingKeys(_ keyPathsForValuesAffectingKeys: [KeyPath: Set], for managedObjectClass: CoreStoreManagedObject.Type) { + internal class func cs_setKeyPathsForValuesAffectingKeys(_ keyPathsForValuesAffectingKeys: [RawKeyPath: Set], for managedObjectClass: CoreStoreManagedObject.Type) { Static.queue.sync(flags: .barrier) { @@ -44,5 +44,5 @@ import CoreData private enum Static { static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue") - static var cache: [ObjectIdentifier: [KeyPath: Set]] = [:] + static var cache: [ObjectIdentifier: [RawKeyPath: Set]] = [:] } diff --git a/Sources/CoreStoreSchema.swift b/Sources/CoreStoreSchema.swift index 8d7bc82..c041ecf 100644 --- a/Sources/CoreStoreSchema.swift +++ b/Sources/CoreStoreSchema.swift @@ -270,7 +270,7 @@ public final class CoreStoreSchema: DynamicSchema { entityDescription.versionHashModifier = entity.versionHashModifier entityDescription.managedObjectClassName = "\(NSStringFromClass(CoreStoreManagedObject.self)).\(NSStringFromClass(entity.type)).\(entity.entityName)" - var keyPathsByAffectedKeyPaths: [KeyPath: Set] = [:] + var keyPathsByAffectedKeyPaths: [RawKeyPath: Set] = [:] func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] { var propertyDescriptions: [NSPropertyDescription] = [] diff --git a/Sources/CustomSchemaMappingProvider.swift b/Sources/CustomSchemaMappingProvider.swift index ae9faf3..a166685 100644 --- a/Sources/CustomSchemaMappingProvider.swift +++ b/Sources/CustomSchemaMappingProvider.swift @@ -210,7 +210,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { /** Accesses the property value via its keyPath. */ - public subscript(attribute: KeyPath) -> Any? { + public subscript(attribute: RawKeyPath) -> Any? { return self.rawObject.cs_accessValueForKVCKey(attribute) } @@ -267,7 +267,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { /** Accesses or mutates the property value via its keyPath. */ - public subscript(attribute: KeyPath) -> Any? { + public subscript(attribute: RawKeyPath) -> Any? { get { return self.rawObject.cs_accessValueForKVCKey(attribute) } set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute) } @@ -304,7 +304,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { // MARK: Internal - internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]) { + internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription]) { self.rawObject = rawObject self.sourceAttributesByDestinationKey = sourceAttributesByDestinationKey @@ -314,7 +314,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { // MARK: FilePrivate fileprivate let rawObject: NSManagedObject - fileprivate let sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription] + fileprivate let sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription] } @@ -477,7 +477,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { let transformedRenamingIdentifiers = Set(destinationAttributes.keys) .intersection(sourceAttributes.keys) - var sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription] = [:] + var sourceAttributesByDestinationKey: [RawKeyPath: NSAttributeDescription] = [:] for renamingIdentifier in transformedRenamingIdentifiers { let sourceAttribute = sourceAttributes[renamingIdentifier]!.attribute @@ -535,7 +535,7 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { let userInfo = mapping.userInfo! let transformer = userInfo[CustomEntityMigrationPolicy.UserInfoKey.transformer]! as! CustomMapping.Transformer - let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPath: NSAttributeDescription] + let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [RawKeyPath: NSAttributeDescription] var destinationObject: UnsafeDestinationObject? try transformer( @@ -585,8 +585,8 @@ public class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider { var insertMappings: Set = [] var copyMappings: Set = [] var transformMappings: Set = [] - var allMappedSourceKeys: [KeyPath: KeyPath] = [:] - var allMappedDestinationKeys: [KeyPath: KeyPath] = [:] + var allMappedSourceKeys: [RawKeyPath: RawKeyPath] = [:] + var allMappedDestinationKeys: [RawKeyPath: RawKeyPath] = [:] let sourceRenamingIdentifiers = sourceModel.cs_resolvedRenamingIdentities() let sourceEntityNames = sourceModel.entitiesByName diff --git a/Sources/DataStack+Transaction.swift b/Sources/DataStack+Transaction.swift index d2ff361..fc8bef7 100644 --- a/Sources/DataStack+Transaction.swift +++ b/Sources/DataStack+Transaction.swift @@ -61,10 +61,6 @@ public extension DataStack { ) transaction.transactionQueue.cs_async { - defer { - - withExtendedLifetime((self, transaction), {}) - } let userInfo: T do { @@ -82,6 +78,10 @@ public extension DataStack { } transaction.autoCommit { (_, error) in + defer { + + withExtendedLifetime((self, transaction), {}) + } if let error = error { failure(error) diff --git a/Sources/DynamicSchema+Convenience.swift b/Sources/DynamicSchema+Convenience.swift index 45b2fbb..8f4cefa 100644 --- a/Sources/DynamicSchema+Convenience.swift +++ b/Sources/DynamicSchema+Convenience.swift @@ -96,49 +96,49 @@ public extension DynamicSchema { case .integer16AttributeType: valueType = Int16.self - if let defaultValue = (attribute.defaultValue as! Int16.ImportableNativeType?).flatMap(Int16.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType), defaultValue != Int16.cs_emptyValue() { defaultString = ", default: \(defaultValue)" } case .integer32AttributeType: valueType = Int32.self - if let defaultValue = (attribute.defaultValue as! Int32.ImportableNativeType?).flatMap(Int32.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType), defaultValue != Int32.cs_emptyValue() { defaultString = ", default: \(defaultValue)" } case .integer64AttributeType: valueType = Int64.self - if let defaultValue = (attribute.defaultValue as! Int64.ImportableNativeType?).flatMap(Int64.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType), defaultValue != Int64.cs_emptyValue() { defaultString = ", default: \(defaultValue)" } case .decimalAttributeType: valueType = NSDecimalNumber.self - if let defaultValue = (attribute.defaultValue as! NSDecimalNumber.ImportableNativeType?).flatMap(NSDecimalNumber.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! NSDecimalNumber.QueryableNativeType?).flatMap(NSDecimalNumber.cs_fromQueryableNativeType), defaultValue != NSDecimalNumber.cs_emptyValue() { defaultString = ", default: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")" } case .doubleAttributeType: valueType = Double.self - if let defaultValue = (attribute.defaultValue as! Double.ImportableNativeType?).flatMap(Double.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType), defaultValue != Double.cs_emptyValue() { defaultString = ", default: \(defaultValue)" } case .floatAttributeType: valueType = Float.self - if let defaultValue = (attribute.defaultValue as! Float.ImportableNativeType?).flatMap(Float.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType), defaultValue != Float.cs_emptyValue() { defaultString = ", default: \(defaultValue)" } case .stringAttributeType: valueType = String.self - if let defaultValue = (attribute.defaultValue as! String.ImportableNativeType?).flatMap(String.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType), defaultValue != String.cs_emptyValue() { // TODO: escape strings @@ -146,20 +146,20 @@ public extension DynamicSchema { } case .booleanAttributeType: valueType = Bool.self - if let defaultValue = (attribute.defaultValue as! Bool.ImportableNativeType?).flatMap(Bool.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType), defaultValue != Bool.cs_emptyValue() { defaultString = ", default: \(defaultValue ? "true" : "false")" } case .dateAttributeType: valueType = Date.self - if let defaultValue = (attribute.defaultValue as! Date.ImportableNativeType?).flatMap(Date.cs_fromImportableNativeType) { + if let defaultValue = (attribute.defaultValue as! Date.QueryableNativeType?).flatMap(Date.cs_fromQueryableNativeType) { defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))" } case .binaryDataAttributeType: valueType = Data.self - if let defaultValue = (attribute.defaultValue as! Data.ImportableNativeType?).flatMap(Data.cs_fromImportableNativeType), + if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType), defaultValue != Data.cs_emptyValue() { let count = defaultValue.count diff --git a/Sources/GroupBy.swift b/Sources/GroupBy.swift index 880bda8..11e7fd2 100644 --- a/Sources/GroupBy.swift +++ b/Sources/GroupBy.swift @@ -37,7 +37,7 @@ public struct GroupBy: QueryClause, Hashable { /** The list of key path strings to group results with */ - public let keyPaths: [KeyPath] + public let keyPaths: [RawKeyPath] /** Initializes a `GroupBy` clause with an empty list of key path strings @@ -53,7 +53,7 @@ public struct GroupBy: QueryClause, Hashable { - parameter keyPath: a key path string to group results with - parameter keyPaths: a series of key path strings to group results with */ - public init(_ keyPath: KeyPath, _ keyPaths: KeyPath...) { + public init(_ keyPath: RawKeyPath, _ keyPaths: RawKeyPath...) { self.init([keyPath] + keyPaths) } @@ -63,7 +63,7 @@ public struct GroupBy: QueryClause, Hashable { - parameter keyPaths: a list of key path strings to group results with */ - public init(_ keyPaths: [KeyPath]) { + public init(_ keyPaths: [RawKeyPath]) { self.keyPaths = keyPaths } diff --git a/Sources/ImportableAttributeType.swift b/Sources/ImportableAttributeType.swift index 3770a5d..5bad2cb 100644 --- a/Sources/ImportableAttributeType.swift +++ b/Sources/ImportableAttributeType.swift @@ -57,25 +57,7 @@ import CoreGraphics In addition, `RawRepresentable` types whose `RawValue` already implements `ImportableAttributeType` only need to declare conformance to `ImportableAttributeType`. */ -public protocol ImportableAttributeType: QueryableAttributeType { - - /** - The `CoreDataNativeType` for this type. - */ - associatedtype ImportableNativeType: QueryableNativeType - - /** - Creates an instance of this type from its `ImportableNativeType` value. - */ - @inline(__always) - static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? - - /** - Creates `ImportableNativeType` value from this instance. - */ - @inline(__always) - func cs_toImportableNativeType() -> ImportableNativeType -} +public protocol ImportableAttributeType: QueryableAttributeType {} // MARK: - EmptyableAttributeType @@ -99,22 +81,6 @@ public protocol EmptyableAttributeType: ImportableAttributeType { extension Bool: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - // MARK: EmptyableAttributeType @@ -130,23 +96,6 @@ extension Bool: ImportableAttributeType, EmptyableAttributeType { extension CGFloat: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> CGFloat? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -161,23 +110,6 @@ extension CGFloat: ImportableAttributeType, EmptyableAttributeType { extension Data: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSData - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -190,47 +122,13 @@ extension Data: ImportableAttributeType, EmptyableAttributeType { // MARK: - Date -extension Date: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSDate - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension Date: ImportableAttributeType {} // MARK: - Double extension Double: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -245,23 +143,6 @@ extension Double: ImportableAttributeType, EmptyableAttributeType { extension Float: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -276,23 +157,6 @@ extension Float: ImportableAttributeType, EmptyableAttributeType { extension Int: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -307,23 +171,6 @@ extension Int: ImportableAttributeType, EmptyableAttributeType { extension Int8: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int8? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -338,23 +185,6 @@ extension Int8: ImportableAttributeType, EmptyableAttributeType { extension Int16: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -369,23 +199,6 @@ extension Int16: ImportableAttributeType, EmptyableAttributeType { extension Int32: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -400,23 +213,6 @@ extension Int32: ImportableAttributeType, EmptyableAttributeType { extension Int64: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -431,23 +227,6 @@ extension Int64: ImportableAttributeType, EmptyableAttributeType { extension NSData: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSData - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @nonobjc @inline(__always) @@ -460,47 +239,13 @@ extension NSData: ImportableAttributeType, EmptyableAttributeType { // MARK: - NSDate -extension NSDate: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSDate - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension NSDate: ImportableAttributeType {} // MARK: - NSNumber extension NSNumber: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSNumber - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @nonobjc @inline(__always) @@ -515,23 +260,6 @@ extension NSNumber: ImportableAttributeType, EmptyableAttributeType { extension NSString: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @nonobjc @inline(__always) @@ -544,69 +272,18 @@ extension NSString: ImportableAttributeType, EmptyableAttributeType { // MARK: - NSURL -extension NSURL: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension NSURL: ImportableAttributeType {} // MARK: - NSUUID -extension NSUUID: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @nonobjc @inline(__always) - public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { - - return self.cs_fromQueryableNativeType(value) - } - - @nonobjc @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension NSUUID: ImportableAttributeType {} // MARK: - String extension String: ImportableAttributeType, EmptyableAttributeType { - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } - - // MARK: EmptyableAttributeType @inline(__always) @@ -619,63 +296,27 @@ extension String: ImportableAttributeType, EmptyableAttributeType { // MARK: - URL -extension URL: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> URL? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension URL: ImportableAttributeType {} // MARK: - UUID -extension UUID: ImportableAttributeType { - - // MARK: ImportableAttributeType - - public typealias ImportableNativeType = NSString - - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> UUID? { - - return self.cs_fromQueryableNativeType(value) - } - - @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { - - return self.cs_toQueryableNativeType() - } -} +extension UUID: ImportableAttributeType {} // MARK: - RawRepresentable extension RawRepresentable where RawValue: ImportableAttributeType { - public typealias ImportableNativeType = RawValue.ImportableNativeType - @inline(__always) - public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { - return RawValue.cs_fromImportableNativeType(value).flatMap({ self.init(rawValue: $0) }) + return RawValue.cs_fromQueryableNativeType(value).flatMap({ self.init(rawValue: $0) }) } @inline(__always) - public func cs_toImportableNativeType() -> ImportableNativeType { + public func cs_toQueryableNativeType() -> QueryableNativeType { - return self.rawValue.cs_toImportableNativeType() + return self.rawValue.cs_toQueryableNativeType() } } diff --git a/Sources/ImportableUniqueObject.swift b/Sources/ImportableUniqueObject.swift index 05dbbfd..7836b1f 100644 --- a/Sources/ImportableUniqueObject.swift +++ b/Sources/ImportableUniqueObject.swift @@ -118,7 +118,7 @@ public protocol ImportableUniqueObject: ImportableObject { // MARK: - ImportableUniqueObject (Default Implementations) -public extension ImportableUniqueObject { +public extension ImportableUniqueObject where UniqueIDType.QueryableNativeType: CoreDataNativeType { var uniqueIDValue: UniqueIDType { @@ -126,7 +126,7 @@ public extension ImportableUniqueObject { return self.cs_toRaw().getValue( forKvcKey: type(of: self).uniqueIDKeyPath, - didGetValue: { UniqueIDType.cs_fromImportableNativeType($0 as! UniqueIDType.ImportableNativeType)! } + didGetValue: { UniqueIDType.cs_fromQueryableNativeType($0 as! UniqueIDType.QueryableNativeType)! } ) } set { @@ -135,10 +135,13 @@ public extension ImportableUniqueObject { .setValue( newValue, forKvcKey: type(of: self).uniqueIDKeyPath, - willSetValue: { ($0.cs_toImportableNativeType() as! CoreDataNativeType) } - ) + willSetValue: { ($0.cs_toQueryableNativeType() as CoreDataNativeType) } + ) } } +} + +public extension ImportableUniqueObject { static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { diff --git a/Sources/ListMonitor.swift b/Sources/ListMonitor.swift index 2be4277..2e1a44e 100644 --- a/Sources/ListMonitor.swift +++ b/Sources/ListMonitor.swift @@ -997,7 +997,7 @@ public final class ListMonitor: Hashable { fileprivate var fetchedResultsController: CoreStoreFetchedResultsController fileprivate let taskGroup = DispatchGroup() - fileprivate let sectionIndexTransformer: (_ sectionName: KeyPath?) -> String? + fileprivate let sectionIndexTransformer: (_ sectionName: RawKeyPath?) -> String? private let isSectioned: Bool diff --git a/Sources/NSEntityDescription+DynamicModel.swift b/Sources/NSEntityDescription+DynamicModel.swift index bcf7bd8..f7a7510 100644 --- a/Sources/NSEntityDescription+DynamicModel.swift +++ b/Sources/NSEntityDescription+DynamicModel.swift @@ -75,12 +75,12 @@ internal extension NSEntityDescription { } } - internal var keyPathsByAffectedKeyPaths: [KeyPath: Set] { + internal var keyPathsByAffectedKeyPaths: [RawKeyPath: Set] { get { if let userInfo = self.userInfo, - let function = userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] as! [KeyPath: Set]? { + let function = userInfo[UserInfoKey.CoreStoreManagedObjectKeyPathsByAffectedKeyPaths] as! [RawKeyPath: Set]? { return function } diff --git a/Sources/NSManagedObject+Convenience.swift b/Sources/NSManagedObject+Convenience.swift index ba30a15..5c272e3 100644 --- a/Sources/NSManagedObject+Convenience.swift +++ b/Sources/NSManagedObject+Convenience.swift @@ -84,7 +84,7 @@ public extension NSManagedObject { - returns: the primitive value for the KVC key */ @nonobjc @inline(__always) - public func getValue(forKvcKey kvcKey: KeyPath) -> Any? { + public func getValue(forKvcKey kvcKey: RawKeyPath) -> Any? { self.willAccessValue(forKey: kvcKey) defer { @@ -102,7 +102,7 @@ public extension NSManagedObject { - returns: the primitive value transformed by the `didGetValue` closure */ @nonobjc @inline(__always) - public func getValue(forKvcKey kvcKey: KeyPath, didGetValue: (Any?) throws -> T) rethrows -> T { + public func getValue(forKvcKey kvcKey: RawKeyPath, didGetValue: (Any?) throws -> T) rethrows -> T { self.willAccessValue(forKey: kvcKey) defer { @@ -121,7 +121,7 @@ public extension NSManagedObject { - returns: the primitive value transformed by the `didGetValue` closure */ @nonobjc @inline(__always) - public func getValue(forKvcKey kvcKey: KeyPath, willGetValue: () throws -> Void, didGetValue: (Any?) throws -> T) rethrows -> T { + public func getValue(forKvcKey kvcKey: RawKeyPath, willGetValue: () throws -> Void, didGetValue: (Any?) throws -> T) rethrows -> T { self.willAccessValue(forKey: kvcKey) defer { @@ -139,7 +139,7 @@ public extension NSManagedObject { - parameter KVCKey: the KVC key */ @nonobjc @inline(__always) - public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath) { + public func setValue(_ value: Any?, forKvcKey KVCKey: RawKeyPath) { self.willChangeValue(forKey: KVCKey) defer { @@ -157,7 +157,7 @@ public extension NSManagedObject { - parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`. */ @nonobjc @inline(__always) - public func setValue(_ value: Any?, forKvcKey KVCKey: KeyPath, didSetValue: () -> Void) { + public func setValue(_ value: Any?, forKvcKey KVCKey: RawKeyPath, didSetValue: () -> Void) { self.willChangeValue(forKey: KVCKey) defer { @@ -177,7 +177,7 @@ public extension NSManagedObject { - parameter didSetValue: called after executing `setPrimitiveValue(forKey:)`. */ @nonobjc @inline(__always) - public func setValue(_ value: T, forKvcKey KVCKey: KeyPath, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows { + public func setValue(_ value: T, forKvcKey KVCKey: RawKeyPath, willSetValue: (T) throws -> Any?, didSetValue: (Any?) -> Void = { _ in }) rethrows { self.willChangeValue(forKey: KVCKey) defer { @@ -212,7 +212,7 @@ public extension NSManagedObject { @available(*, deprecated, renamed: "getValue(forKvcKey:)") @nonobjc - public func accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? { + public func accessValueForKVCKey(_ KVCKey: RawKeyPath) -> Any? { self.willAccessValue(forKey: KVCKey) defer { @@ -225,7 +225,7 @@ public extension NSManagedObject { @available(*, deprecated, renamed: "getValue(forKvcKey:didGetValue:)") @discardableResult @nonobjc - public func accessValueForKVCKey(_ KVCKey: KeyPath, _ didAccessPrimitiveValue: (Any?) throws -> T) rethrows -> T { + public func accessValueForKVCKey(_ KVCKey: RawKeyPath, _ didAccessPrimitiveValue: (Any?) throws -> T) rethrows -> T { self.willAccessValue(forKey: KVCKey) defer { @@ -237,7 +237,7 @@ public extension NSManagedObject { @available(*, deprecated, renamed: "setValue(_:forKvcKey:)") @nonobjc - public func setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) { + public func setValue(_ value: Any?, forKVCKey KVCKey: RawKeyPath) { self.willChangeValue(forKey: KVCKey) defer { @@ -250,7 +250,7 @@ public extension NSManagedObject { @available(*, deprecated, renamed: "setValue(_:forKvcKey:didSetValue:)") @discardableResult @nonobjc - public func setValue(_ value: Any?, forKVCKey KVCKey: KeyPath, _ didSetPrimitiveValue: (Any?) throws -> T) rethrows -> T { + public func setValue(_ value: Any?, forKVCKey KVCKey: RawKeyPath, _ didSetPrimitiveValue: (Any?) throws -> T) rethrows -> T { self.willChangeValue(forKey: KVCKey) defer { diff --git a/Sources/NSManagedObject+ObjectiveC.swift b/Sources/NSManagedObject+ObjectiveC.swift index 9caf93e..fdb702d 100644 --- a/Sources/NSManagedObject+ObjectiveC.swift +++ b/Sources/NSManagedObject+ObjectiveC.swift @@ -38,7 +38,7 @@ public extension NSManagedObject { - returns: the primitive value for the KVC key */ @objc - public func cs_accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? { + public func cs_accessValueForKVCKey(_ KVCKey: RawKeyPath) -> Any? { return self.getValue(forKvcKey: KVCKey) } @@ -50,7 +50,7 @@ public extension NSManagedObject { - parameter KVCKey: the KVC key */ @objc - public func cs_setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) { + public func cs_setValue(_ value: Any?, forKVCKey KVCKey: RawKeyPath) { self.setValue(value, forKvcKey: KVCKey) } diff --git a/Sources/ObjectObserver.swift b/Sources/ObjectObserver.swift index 88faba1..0a86067 100644 --- a/Sources/ObjectObserver.swift +++ b/Sources/ObjectObserver.swift @@ -61,7 +61,7 @@ public protocol ObjectObserver: class { - parameter object: the `DynamicObject` instance being observed - parameter changedPersistentKeys: a `Set` of key paths for the attributes that were changed. Note that `changedPersistentKeys` only contains keys for attributes/relationships present in the persistent store, thus transient properties will not be reported. */ - func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) /** Handles processing right after `object` is deleted. (Optional) @@ -81,7 +81,7 @@ public extension ObjectObserver { public func objectMonitor(_ monitor: ObjectMonitor, willUpdateObject object: ObjectEntityType) { } - public func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) { } + public func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) { } public func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: ObjectEntityType) { } } diff --git a/Sources/OrderBy.swift b/Sources/OrderBy.swift index e79fafa..6b4d033 100644 --- a/Sources/OrderBy.swift +++ b/Sources/OrderBy.swift @@ -27,9 +27,9 @@ import Foundation import CoreData -// MARK: - KeyPath +// MARK: - RawKeyPath -public typealias KeyPath = String +public typealias RawKeyPath = String // MARK: - SortKey @@ -40,14 +40,14 @@ public typealias KeyPath = String public enum SortKey { /** - Indicates that the `KeyPath` should be sorted in ascending order + Indicates that the `RawKeyPath` should be sorted in ascending order */ - case ascending(KeyPath) + case ascending(RawKeyPath) /** - Indicates that the `KeyPath` should be sorted in descending order + Indicates that the `RawKeyPath` should be sorted in descending order */ - case descending(KeyPath) + case descending(RawKeyPath) } diff --git a/Sources/QueryableAttributeType.swift b/Sources/QueryableAttributeType.swift index 974bd06..a7ae995 100644 --- a/Sources/QueryableAttributeType.swift +++ b/Sources/QueryableAttributeType.swift @@ -64,7 +64,7 @@ public protocol QueryableAttributeType: Hashable, SelectResultType { /** The `CoreDataNativeType` for this type when used in `Select` clauses. */ - associatedtype QueryableNativeType: CoreDataNativeType + associatedtype QueryableNativeType /** The `NSAttributeType` for this type when used in `Select` clauses. @@ -111,7 +111,7 @@ extension Bool: QueryableAttributeType { @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { - return self as NSNumber + return self as QueryableNativeType } } @@ -133,7 +133,7 @@ extension CGFloat: QueryableAttributeType { @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { - return self as NSNumber + return self as QueryableNativeType } } @@ -155,7 +155,7 @@ extension Data: QueryableAttributeType { @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { - return self as NSData + return self as QueryableNativeType } } @@ -342,7 +342,10 @@ extension NSData: QueryableAttributeType { public typealias QueryableNativeType = NSData - public static let cs_rawAttributeType: NSAttributeType = .binaryDataAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .binaryDataAttributeType + } @nonobjc @inline(__always) public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { @@ -369,7 +372,10 @@ extension NSDate: QueryableAttributeType { public typealias QueryableNativeType = NSDate - public static let cs_rawAttributeType: NSAttributeType = .dateAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .dateAttributeType + } @nonobjc @inline(__always) public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { @@ -407,7 +413,10 @@ extension NSManagedObjectID: QueryableAttributeType { public typealias QueryableNativeType = NSManagedObjectID - public static let cs_rawAttributeType: NSAttributeType = .objectIDAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .objectIDAttributeType + } @nonobjc @inline(__always) public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { @@ -440,7 +449,7 @@ extension NSNull: QueryableAttributeType { } @nonobjc @inline(__always) - public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { @inline(__always) func forceCast(_ value: Any) -> T? { @@ -494,7 +503,10 @@ extension NSString: QueryableAttributeType { public typealias QueryableNativeType = NSString - public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .stringAttributeType + } @nonobjc @inline(__always) public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { @@ -521,10 +533,13 @@ extension NSURL: QueryableAttributeType { public typealias QueryableNativeType = NSString - public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .stringAttributeType + } @nonobjc @inline(__always) - public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { return self.init(string: value as String) } @@ -543,10 +558,13 @@ extension NSUUID: QueryableAttributeType { public typealias QueryableNativeType = NSString - public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType + public class var cs_rawAttributeType: NSAttributeType { + + return .stringAttributeType + } @nonobjc @inline(__always) - public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { return self.init(uuidString: value.lowercased) } @@ -576,7 +594,7 @@ extension String: QueryableAttributeType { @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { - return self as NSString + return self as QueryableNativeType } } diff --git a/Sources/Relationship.swift b/Sources/Relationship.swift index 365ae93..f93ac48 100644 --- a/Sources/Relationship.swift +++ b/Sources/Relationship.swift @@ -95,7 +95,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, @@ -129,7 +129,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToOne, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, @@ -164,7 +164,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyOrdered, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, @@ -199,7 +199,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyUnordered, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, @@ -234,14 +234,14 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isToMany = false internal let isOrdered = false internal let deleteRule: NSDeleteRule internal let minCount: Int = 0 internal let maxCount: Int = 1 - internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) + internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) internal let versionHashModifier: String? internal let renamingIdentifier: String? internal let affectedByKeyPaths: () -> Set @@ -286,7 +286,7 @@ public enum RelationshipContainer { // MARK: Private - private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { + private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { self.keyPath = keyPath self.deleteRule = deleteRule.nativeValue @@ -333,7 +333,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, minCount: Int = 0, maxCount: Int = 0, deleteRule: DeleteRule = .nullify, @@ -373,7 +373,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToOne, @@ -414,7 +414,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToManyOrdered, @@ -455,7 +455,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, minCount: Int = 0, maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToManyUnordered, @@ -494,7 +494,7 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isToMany = true internal let isOptional = true @@ -502,7 +502,7 @@ public enum RelationshipContainer { internal let deleteRule: NSDeleteRule internal let minCount: Int internal let maxCount: Int - internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) + internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) internal let versionHashModifier: String? internal let renamingIdentifier: String? internal let affectedByKeyPaths: () -> Set @@ -599,7 +599,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, @@ -639,7 +639,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToOne, deleteRule: DeleteRule = .nullify, minCount: Int = 0, @@ -680,7 +680,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyOrdered, deleteRule: DeleteRule = .nullify, minCount: Int = 0, @@ -721,7 +721,7 @@ public enum RelationshipContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyUnordered, deleteRule: DeleteRule = .nullify, minCount: Int = 0, @@ -760,7 +760,7 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isToMany = true internal let isOptional = true @@ -768,7 +768,7 @@ public enum RelationshipContainer { internal let deleteRule: NSDeleteRule internal let minCount: Int internal let maxCount: Int - internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) + internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) internal let versionHashModifier: String? internal let renamingIdentifier: String? internal let affectedByKeyPaths: () -> Set @@ -813,7 +813,7 @@ public enum RelationshipContainer { // MARK: Private - private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { + private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { self.keyPath = keyPath self.deleteRule = deleteRule.nativeValue @@ -1186,11 +1186,11 @@ extension RelationshipContainer.ToManyUnordered { internal protocol RelationshipProtocol: class { - var keyPath: KeyPath { get } + var keyPath: RawKeyPath { get } var isToMany: Bool { get } var isOrdered: Bool { get } var deleteRule: NSDeleteRule { get } - var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) { get } + var inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) { get } var affectedByKeyPaths: () -> Set { get } var parentObject: () -> CoreStoreObject { get set } var versionHashModifier: String? { get } diff --git a/Sources/SectionBy.swift b/Sources/SectionBy.swift index 561aadf..c847ac7 100644 --- a/Sources/SectionBy.swift +++ b/Sources/SectionBy.swift @@ -47,7 +47,7 @@ public struct SectionBy { - parameter sectionKeyPath: the key path to use to group the objects into sections */ - public init(_ sectionKeyPath: KeyPath) { + public init(_ sectionKeyPath: RawKeyPath) { self.init(sectionKeyPath, { $0 }) } @@ -59,7 +59,7 @@ public struct SectionBy { - parameter sectionKeyPath: the key path to use to group the objects into sections - parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name */ - public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) { + public init(_ sectionKeyPath: RawKeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) { self.sectionKeyPath = sectionKeyPath self.sectionIndexTransformer = sectionIndexTransformer @@ -68,6 +68,6 @@ public struct SectionBy { // MARK: Internal - internal let sectionKeyPath: KeyPath + internal let sectionKeyPath: RawKeyPath internal let sectionIndexTransformer: (_ sectionName: String?) -> String? } diff --git a/Sources/Select.swift b/Sources/Select.swift index 468d5e5..10a9149 100644 --- a/Sources/Select.swift +++ b/Sources/Select.swift @@ -74,7 +74,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter keyPath: the attribute name - returns: a `SelectTerm` to a `Select` clause for querying an entity attribute */ - public static func attribute(_ keyPath: KeyPath) -> SelectTerm { + public static func attribute(_ keyPath: RawKeyPath) -> SelectTerm { return ._attribute(keyPath) } @@ -91,7 +91,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average()" is used - returns: a `SelectTerm` to a `Select` clause for querying the average value of an attribute */ - public static func average(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm { + public static func average(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm { return ._aggregate( function: "average:", @@ -113,7 +113,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count()" is used - returns: a `SelectTerm` to a `Select` clause for a count query */ - public static func count(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm { + public static func count(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm { return ._aggregate( function: "count:", @@ -135,7 +135,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max()" is used - returns: a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute */ - public static func maximum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm { + public static func maximum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm { return ._aggregate( function: "max:", @@ -157,7 +157,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min()" is used - returns: a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute */ - public static func minimum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm { + public static func minimum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm { return ._aggregate( function: "min:", @@ -179,7 +179,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum()" is used - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute */ - public static func sum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm { + public static func sum(_ keyPath: RawKeyPath, as alias: RawKeyPath? = nil) -> SelectTerm { return ._aggregate( function: "sum:", @@ -202,7 +202,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute */ - public static func objectID(as alias: KeyPath? = nil) -> SelectTerm { + public static func objectID(as alias: RawKeyPath? = nil) -> SelectTerm { return ._identity( alias: alias ?? "objectID", @@ -213,17 +213,17 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { // MARK: ExpressibleByStringLiteral - public init(stringLiteral value: KeyPath) { + public init(stringLiteral value: RawKeyPath) { self = ._attribute(value) } - public init(unicodeScalarLiteral value: KeyPath) { + public init(unicodeScalarLiteral value: RawKeyPath) { self = ._attribute(value) } - public init(extendedGraphemeClusterLiteral value: KeyPath) { + public init(extendedGraphemeClusterLiteral value: RawKeyPath) { self = ._attribute(value) } @@ -274,8 +274,8 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { // MARK: Internal - case _attribute(KeyPath) - case _aggregate(function: String, keyPath: KeyPath, alias: String, nativeType: NSAttributeType) + case _attribute(RawKeyPath) + case _aggregate(function: String, keyPath: RawKeyPath, alias: String, nativeType: NSAttributeType) case _identity(alias: String, nativeType: NSAttributeType) } @@ -479,7 +479,7 @@ internal extension Collection where Iterator.Element == SelectTerm { fetchRequest.propertiesToFetch = propertiesToFetch } - internal func keyPathForFirstSelectTerm() -> KeyPath { + internal func keyPathForFirstSelectTerm() -> RawKeyPath { switch self.first! { diff --git a/Sources/Value.swift b/Sources/Value.swift index 72f94ce..f2940fe 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -117,7 +117,7 @@ public enum ValueContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, @@ -130,7 +130,7 @@ public enum ValueContainer { self.keyPath = keyPath self.isIndexed = isIndexed self.isTransient = isTransient - self.defaultValue = `default`.cs_toImportableNativeType() + self.defaultValue = `default`.cs_toQueryableNativeType() self.versionHashModifier = versionHashModifier self.renamingIdentifier = renamingIdentifier self.customGetter = customGetter @@ -156,7 +156,7 @@ public enum ValueContainer { return object.rawObject!.getValue( forKvcKey: self.keyPath, - didGetValue: { V.cs_fromImportableNativeType($0 as! V.ImportableNativeType)! } + didGetValue: { V.cs_fromQueryableNativeType($0 as! V.QueryableNativeType)! } ) } ) @@ -179,7 +179,7 @@ public enum ValueContainer { object.rawObject!.setValue( newValue, forKvcKey: self.keyPath, - willSetValue: { $0.cs_toImportableNativeType() } + willSetValue: { $0.cs_toQueryableNativeType() } ) }, newValue @@ -195,7 +195,7 @@ public enum ValueContainer { return V.cs_rawAttributeType } - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isOptional = false internal let isIndexed: Bool @@ -262,7 +262,7 @@ public enum ValueContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, @@ -275,7 +275,7 @@ public enum ValueContainer { self.keyPath = keyPath self.isIndexed = isIndexed self.isTransient = isTransient - self.defaultValue = `default`?.cs_toImportableNativeType() + self.defaultValue = `default`?.cs_toQueryableNativeType() self.versionHashModifier = versionHashModifier self.renamingIdentifier = renamingIdentifier self.customGetter = customGetter @@ -301,7 +301,7 @@ public enum ValueContainer { return object.rawObject!.getValue( forKvcKey: self.keyPath, - didGetValue: { ($0 as! V.ImportableNativeType?).flatMap(V.cs_fromImportableNativeType) } + didGetValue: { ($0 as! V.QueryableNativeType?).flatMap(V.cs_fromQueryableNativeType) } ) } ) @@ -324,7 +324,7 @@ public enum ValueContainer { object.rawObject!.setValue( newValue, forKvcKey: self.keyPath, - willSetValue: { $0?.cs_toImportableNativeType() } + willSetValue: { $0?.cs_toQueryableNativeType() } ) }, newValue @@ -340,7 +340,7 @@ public enum ValueContainer { return V.cs_rawAttributeType } - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isOptional = true internal let isIndexed: Bool internal let isTransient: Bool @@ -386,7 +386,7 @@ public extension ValueContainer.Required where V: EmptyableAttributeType { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public convenience init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, @@ -462,7 +462,7 @@ public enum TransformableContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, @@ -539,7 +539,7 @@ public enum TransformableContainer { return .transformableAttributeType } - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isOptional = false internal let isIndexed: Bool @@ -600,7 +600,7 @@ public enum TransformableContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: KeyPath, + _ keyPath: RawKeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, @@ -677,7 +677,7 @@ public enum TransformableContainer { return .transformableAttributeType } - public let keyPath: KeyPath + public let keyPath: RawKeyPath internal let isOptional = true internal let isIndexed: Bool @@ -995,7 +995,7 @@ internal protocol AttributeProtocol: class { static var attributeType: NSAttributeType { get } - var keyPath: KeyPath { get } + var keyPath: RawKeyPath { get } var isOptional: Bool { get } var isIndexed: Bool { get } var isTransient: Bool { get } diff --git a/Sources/Where.swift b/Sources/Where.swift index 76a095b..c818d18 100644 --- a/Sources/Where.swift +++ b/Sources/Where.swift @@ -109,7 +109,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { - parameter keyPath: the keyPath to compare with - parameter value: the arguments for the `==` operator */ - public init(_ keyPath: KeyPath, isEqualTo value: Void?) { + public init(_ keyPath: RawKeyPath, isEqualTo value: Void?) { self.init(NSPredicate(format: "\(keyPath) == nil")) } @@ -120,7 +120,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { - parameter keyPath: the keyPath to compare with - parameter value: the arguments for the `==` operator */ - public init(_ keyPath: KeyPath, isEqualTo value: T?) { + public init(_ keyPath: RawKeyPath, isEqualTo value: T?) { switch value { @@ -139,7 +139,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { - parameter keyPath: the keyPath to compare with - parameter object: the arguments for the `==` operator */ - public init(_ keyPath: KeyPath, isEqualTo object: T?) { + public init(_ keyPath: RawKeyPath, isEqualTo object: T?) { switch object { @@ -158,7 +158,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { - parameter keyPath: the keyPath to compare with - parameter list: the sequence to check membership of */ - public init(_ keyPath: KeyPath, isMemberOf list: S) where S.Iterator.Element: QueryableAttributeType { + public init(_ keyPath: RawKeyPath, isMemberOf list: S) where S.Iterator.Element: QueryableAttributeType { self.init(NSPredicate(format: "\(keyPath) IN %@", list.map({ $0.cs_toQueryableNativeType() }) as NSArray)) } @@ -169,7 +169,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable { - parameter keyPath: the keyPath to compare with - parameter list: the sequence to check membership of */ - public init(_ keyPath: KeyPath, isMemberOf list: S) where S.Iterator.Element: DynamicObject { + public init(_ keyPath: RawKeyPath, isMemberOf list: S) where S.Iterator.Element: DynamicObject { self.init(NSPredicate(format: "\(keyPath) IN %@", list.map({ $0.cs_id() }) as NSArray)) } From 23e12c45397ae14a77258ddc3398342c756256b2 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Fri, 9 Jun 2017 11:29:51 +0900 Subject: [PATCH 03/17] add constraints to Value.Optional and Value.Required native types --- Sources/Value.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Value.swift b/Sources/Value.swift index f2940fe..97fd6b2 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -86,7 +86,7 @@ public enum ValueContainer { ``` - Important: `Value.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. */ - public final class Required: AttributeProtocol { + public final class Required: AttributeProtocol where V.QueryableNativeType: CoreDataNativeType { /** Initializes the metadata for the property. @@ -231,7 +231,7 @@ public enum ValueContainer { ``` - Important: `Value.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. */ - public final class Optional: AttributeProtocol { + public final class Optional: AttributeProtocol where V.QueryableNativeType: CoreDataNativeType { /** Initializes the metadata for the property. From fd3a9b00eccb624226bba5c2d6c2aedf5f4d57f4 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Fri, 23 Jun 2017 17:58:34 +0900 Subject: [PATCH 04/17] fix FRC breaking again for iOS 8 --- Sources/FetchedResultsControllerDelegate.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/FetchedResultsControllerDelegate.swift b/Sources/FetchedResultsControllerDelegate.swift index dc1d251..613b418 100644 --- a/Sources/FetchedResultsControllerDelegate.swift +++ b/Sources/FetchedResultsControllerDelegate.swift @@ -185,6 +185,10 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult ) return } + guard #available(iOS 9.0, tvOS 9.0, watchOS 9.0, *) else { + + return + } self.handler?.controller( controller, didChangeObject: anObject, From 5c0e78bd53e7227958a0e1a9a8bb7b78f006edae Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Sat, 5 Aug 2017 00:03:17 +0900 Subject: [PATCH 05/17] Deleted EmptyableAttributeType and require "initial" parameter for Value.Required --- CoreStore.xcodeproj/project.pbxproj | 42 +- CoreStoreTests/DynamicModelTests.swift | 7 +- Sources/AttributeProtocol.swift | 47 ++ Sources/CoreStoreSchema.swift | 8 +- Sources/DynamicSchema+Convenience.swift | 51 +- Sources/ImportableAttributeType.swift | 173 +------ Sources/Relationship.swift | 84 ++-- Sources/RelationshipProtocol.swift | 45 ++ Sources/Transformable.swift | 597 ++++++++++++++++++++++ Sources/Value.swift | 633 +++--------------------- 10 files changed, 867 insertions(+), 820 deletions(-) create mode 100644 Sources/AttributeProtocol.swift create mode 100644 Sources/RelationshipProtocol.swift create mode 100644 Sources/Transformable.swift diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index c34ff5f..a390071 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -449,6 +449,18 @@ B580857A1CDF808C004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; }; B580857B1CDF808D004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; }; B580857C1CDF808F004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; }; + B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; }; + B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; }; + B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; }; + B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */; }; + B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; }; + B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; }; + B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; }; + B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */; }; + B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; }; + B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; }; + B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; }; + B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5831B791F34ACBA00A9F647 /* Transformable.swift */; }; B58B22F51C93C1BA00521925 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A53019C5C6DA005002A5 /* CoreStore.framework */; }; B58D0C631EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; }; B58D0C641EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */; }; @@ -816,6 +828,9 @@ B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = ""; }; B57D27C11D0BC20100539C58 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = ""; }; B58085741CDF7F00004C2EEB /* SetupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetupTests.swift; sourceTree = ""; }; + B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributeProtocol.swift; sourceTree = ""; }; + B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipProtocol.swift; sourceTree = ""; }; + B5831B791F34ACBA00A9F647 /* Transformable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transformable.swift; sourceTree = ""; }; B58D0C621EAA0C7E003EDD87 /* NSManagedObject+DynamicModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+DynamicModel.swift"; sourceTree = ""; }; B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvenienceTests.swift; sourceTree = ""; }; B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableSource.swift; sourceTree = ""; }; @@ -1235,17 +1250,26 @@ children = ( B5D339D71E9489AB00C880DE /* CoreStoreObject.swift */, B53CA9A11EF1EF1600E0F440 /* PartialObject.swift */, + B5831B6E1F3355C300A9F647 /* Properties */, B52F74391E9B8724005F3DAC /* Dynamic Schema */, B5D339DC1E9489C700C880DE /* DynamicObject.swift */, B52F742E1E9B50D0005F3DAC /* SchemaHistory.swift */, B5D339E61E9493A500C880DE /* Entity.swift */, - B5D33A001E96012400C880DE /* Relationship.swift */, - B5D339E11E948C3600C880DE /* Value.swift */, B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */, ); name = "Dynamic Models"; sourceTree = ""; }; + B5831B6E1F3355C300A9F647 /* Properties */ = { + isa = PBXGroup; + children = ( + B5D33A001E96012400C880DE /* Relationship.swift */, + B5D339E11E948C3600C880DE /* Value.swift */, + B5831B791F34ACBA00A9F647 /* Transformable.swift */, + ); + name = Properties; + sourceTree = ""; + }; B5A5F26B1CAFF8D0004AB9AF /* Swift */ = { isa = PBXGroup; children = ( @@ -1434,6 +1458,8 @@ B5E84F291AFF849C0064E85B /* Internal */ = { isa = PBXGroup; children = ( + B5831B6F1F34AC3400A9F647 /* AttributeProtocol.swift */, + B5831B741F34AC7A00A9F647 /* RelationshipProtocol.swift */, B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */, B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */, B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */, @@ -1814,6 +1840,7 @@ B5ECDC1D1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, + B5831B751F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5D339F11E94AF5800C880DE /* CoreStoreStrings.swift in Sources */, B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */, @@ -1906,6 +1933,7 @@ B59FA0AE1CCBAC95007C9BCA /* ICloudStore.swift in Sources */, B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */, B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */, + B5831B7A1F34ACBA00A9F647 /* Transformable.swift in Sources */, B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B53FBA1E1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, B549F65E1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */, @@ -1921,6 +1949,7 @@ B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */, B53FBA041CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */, + B5831B701F34AC3400A9F647 /* AttributeProtocol.swift in Sources */, B5DBE2CD1C9914A900B5CEFA /* CSCoreStore.swift in Sources */, B546F95D1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B5D339E71E9493A500C880DE /* Entity.swift in Sources */, @@ -2000,6 +2029,7 @@ B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, + B5831B761F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, B5E1B5AA1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5D339F21E94AF5800C880DE /* CoreStoreStrings.swift in Sources */, B5D3F6461C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, @@ -2092,6 +2122,7 @@ 82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */, 82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */, B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, + B5831B7B1F34ACBA00A9F647 /* Transformable.swift in Sources */, B53FBA201CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, 82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */, B549F65F1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */, @@ -2107,6 +2138,7 @@ B53FBA061CAB300C00F0D40A /* CSMigrationType.swift in Sources */, 82BA18BE1C4BBD4A00A0916E /* Tweak.swift in Sources */, B5DBE2CE1C9914A900B5CEFA /* CSCoreStore.swift in Sources */, + B5831B711F34AC3400A9F647 /* AttributeProtocol.swift in Sources */, B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B5ECDC0D1CA8161B00C7F112 /* CSGroupBy.swift in Sources */, B5D339E81E9493A500C880DE /* Entity.swift in Sources */, @@ -2186,6 +2218,7 @@ B5D3F6481C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, B5220E1C1D130801009BC71E /* FetchedResultsControllerDelegate.swift in Sources */, B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */, + B5831B781F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */, B5D339F41E94AF5800C880DE /* CoreStoreStrings.swift in Sources */, B5220E241D13085E009BC71E /* NSFetchedResultsController+Convenience.swift in Sources */, @@ -2278,6 +2311,7 @@ B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */, B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */, B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */, + B5831B7D1F34ACBA00A9F647 /* Transformable.swift in Sources */, B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */, B5220E151D130663009BC71E /* CoreStore+Observing.swift in Sources */, B549F6611E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */, @@ -2293,6 +2327,7 @@ B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */, B5519A5C1CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */, B5DBE2D51C991B3E00B5CEFA /* CSDataStack.swift in Sources */, + B5831B731F34AC3400A9F647 /* AttributeProtocol.swift in Sources */, B5AEFAB81C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, B598514B1C90289F00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, B5D339EA1E9493A500C880DE /* Entity.swift in Sources */, @@ -2372,6 +2407,7 @@ B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, + B5831B771F34AC7A00A9F647 /* RelationshipProtocol.swift in Sources */, B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, B5D339F31E94AF5800C880DE /* CoreStoreStrings.swift in Sources */, B5E1B5A01CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, @@ -2464,6 +2500,7 @@ B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */, B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */, B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, + B5831B7C1F34ACBA00A9F647 /* Transformable.swift in Sources */, B53FBA211CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */, B549F6601E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */, @@ -2479,6 +2516,7 @@ B53FBA071CAB300C00F0D40A /* CSMigrationType.swift in Sources */, B56321841BD65216006C9394 /* DefaultLogger.swift in Sources */, B5DBE2CF1C9914A900B5CEFA /* CSCoreStore.swift in Sources */, + B5831B721F34AC3400A9F647 /* AttributeProtocol.swift in Sources */, B546F95F1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B5ECDC0E1CA8161B00C7F112 /* CSGroupBy.swift in Sources */, B5D339E91E9493A500C880DE /* Entity.swift in Sources */, diff --git a/CoreStoreTests/DynamicModelTests.swift b/CoreStoreTests/DynamicModelTests.swift index 20081bf..20686f4 100644 --- a/CoreStoreTests/DynamicModelTests.swift +++ b/CoreStoreTests/DynamicModelTests.swift @@ -37,7 +37,7 @@ import CoreStore class Animal: CoreStoreObject { - let species = Value.Required("species", default: "Swift") + let species = Value.Required("species", initial: "Swift") let master = Relationship.ToOne("master") let color = Transformable.Optional("color") } @@ -45,7 +45,7 @@ class Animal: CoreStoreObject { class Dog: Animal { let nickname = Value.Optional("nickname") - let age = Value.Required("age", default: 1) + let age = Value.Required("age", initial: 1) let friends = Relationship.ToManyOrdered("friends") let friendedBy = Relationship.ToManyUnordered("friendedBy", inverse: { $0.friends }) } @@ -54,12 +54,13 @@ class Person: CoreStoreObject { let title = Value.Required( "title", - default: "Mr.", + initial: "Mr.", customSetter: Person.setTitle ) let name = Value.Required( "name", + initial: "", customSetter: Person.setName ) diff --git a/Sources/AttributeProtocol.swift b/Sources/AttributeProtocol.swift new file mode 100644 index 0000000..9d6c017 --- /dev/null +++ b/Sources/AttributeProtocol.swift @@ -0,0 +1,47 @@ +// +// AttributeProtocol.swift +// CoreStore +// +// Copyright © 2017 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import Foundation +import CoreData + + +// MARK: - AttributeProtocol + +internal protocol AttributeProtocol: class { + + static var attributeType: NSAttributeType { get } + + var keyPath: RawKeyPath { get } + var isOptional: Bool { get } + var isIndexed: Bool { get } + var isTransient: Bool { get } + var versionHashModifier: () -> String? { get } + var renamingIdentifier: () -> String? { get } + var defaultValue: () -> Any? { get } + var affectedByKeyPaths: () -> Set { get } + weak var parentObject: CoreStoreObject? { get set } + var getter: CoreStoreManagedObject.CustomGetter? { get } + var setter: CoreStoreManagedObject.CustomSetter? { get } +} diff --git a/Sources/CoreStoreSchema.swift b/Sources/CoreStoreSchema.swift index 0e11a7a..c685d6b 100644 --- a/Sources/CoreStoreSchema.swift +++ b/Sources/CoreStoreSchema.swift @@ -295,8 +295,8 @@ public final class CoreStoreSchema: DynamicSchema { description.isIndexed = attribute.isIndexed description.defaultValue = attribute.defaultValue() description.isTransient = attribute.isTransient - description.versionHashModifier = attribute.versionHashModifier - description.renamingIdentifier = attribute.renamingIdentifier + description.versionHashModifier = attribute.versionHashModifier() + description.renamingIdentifier = attribute.renamingIdentifier() propertyDescriptions.append(description) keyPathsByAffectedKeyPaths[attribute.keyPath] = attribute.affectedByKeyPaths() customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter) @@ -308,8 +308,8 @@ public final class CoreStoreSchema: DynamicSchema { description.maxCount = relationship.maxCount description.isOrdered = relationship.isOrdered description.deleteRule = relationship.deleteRule - description.versionHashModifier = relationship.versionHashModifier - description.renamingIdentifier = relationship.renamingIdentifier + description.versionHashModifier = relationship.versionHashModifier() + description.renamingIdentifier = relationship.renamingIdentifier() propertyDescriptions.append(description) keyPathsByAffectedKeyPaths[relationship.keyPath] = relationship.affectedByKeyPaths() diff --git a/Sources/DynamicSchema+Convenience.swift b/Sources/DynamicSchema+Convenience.swift index 8f4cefa..d11d964 100644 --- a/Sources/DynamicSchema+Convenience.swift +++ b/Sources/DynamicSchema+Convenience.swift @@ -96,71 +96,62 @@ public extension DynamicSchema { case .integer16AttributeType: valueType = Int16.self - if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType), - defaultValue != Int16.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue)" + defaultString = ", initial: \(defaultValue)" } case .integer32AttributeType: valueType = Int32.self - if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType), - defaultValue != Int32.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue)" + defaultString = ", initial: \(defaultValue)" } case .integer64AttributeType: valueType = Int64.self - if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType), - defaultValue != Int64.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue)" + defaultString = ", initial: \(defaultValue)" } case .decimalAttributeType: valueType = NSDecimalNumber.self - if let defaultValue = (attribute.defaultValue as! NSDecimalNumber.QueryableNativeType?).flatMap(NSDecimalNumber.cs_fromQueryableNativeType), - defaultValue != NSDecimalNumber.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! NSDecimalNumber.QueryableNativeType?).flatMap(NSDecimalNumber.cs_fromQueryableNativeType) { - defaultString = ", default: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")" + defaultString = ", initial: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")" } case .doubleAttributeType: valueType = Double.self - if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType), - defaultValue != Double.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue)" + defaultString = ", initial: \(defaultValue)" } case .floatAttributeType: valueType = Float.self - if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType), - defaultValue != Float.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue)" + defaultString = ", initial: \(defaultValue)" } case .stringAttributeType: valueType = String.self - if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType), - defaultValue != String.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType) { // TODO: escape strings - defaultString = ", default: \"\(defaultValue)\"" + defaultString = ", initial: \"\(defaultValue)\"" } case .booleanAttributeType: valueType = Bool.self - if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType), - defaultValue != Bool.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType) { - defaultString = ", default: \(defaultValue ? "true" : "false")" + defaultString = ", initial: \(defaultValue ? "true" : "false")" } case .dateAttributeType: valueType = Date.self if let defaultValue = (attribute.defaultValue as! Date.QueryableNativeType?).flatMap(Date.cs_fromQueryableNativeType) { - defaultString = ", default: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))" + defaultString = ", initial: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))" } case .binaryDataAttributeType: valueType = Data.self - if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType), - defaultValue != Data.cs_emptyValue() { + if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType) { let count = defaultValue.count let bytes = defaultValue.withUnsafeBytes { (pointer: UnsafePointer) in @@ -168,7 +159,7 @@ public extension DynamicSchema { return (0 ..< (count / MemoryLayout.size)) .map({ "\("0x\(String(pointer[$0], radix: 16, uppercase: false))")" }) } - defaultString = ", default: Data(bytes: [\(bytes.joined(separator: ", "))])" + defaultString = ", initial: Data(bytes: [\(bytes.joined(separator: ", "))])" } case .transformableAttributeType: if let attributeValueClassName = attribute.attributeValueClassName { @@ -181,11 +172,11 @@ public extension DynamicSchema { } if let defaultValue = attribute.defaultValue { - defaultString = ", default: /* \"\(defaultValue)\" */" + defaultString = ", initial: /* \"\(defaultValue)\" */" } else if !attribute.isOptional { - defaultString = ", default: /* required */" + defaultString = ", initial: /* required */" } default: fatalError("Unsupported attribute type: \(attribute.attributeType.rawValue)") diff --git a/Sources/ImportableAttributeType.swift b/Sources/ImportableAttributeType.swift index 5bad2cb..5c3dd18 100644 --- a/Sources/ImportableAttributeType.swift +++ b/Sources/ImportableAttributeType.swift @@ -60,64 +60,18 @@ import CoreGraphics public protocol ImportableAttributeType: QueryableAttributeType {} -// MARK: - EmptyableAttributeType - -/** - `ImportableAttributeType`s that have a natural "empty" value. Example: `0` for `Int`, `""` for `String`. - - - Discussion: Not all `ImportableAttributeType`s can have empty values. `URL`s and `Date`s for example have no obvious empty values. - */ -public protocol EmptyableAttributeType: ImportableAttributeType { - - /** - Returns the default "empty" value for this type. - */ - @inline(__always) - static func cs_emptyValue() -> Self -} - - // MARK: - Bool -extension Bool: ImportableAttributeType, EmptyableAttributeType { - - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Bool { - - return false - } -} - +extension Bool: ImportableAttributeType {} // MARK: - CGFloat -extension CGFloat: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> CGFloat { - - return 0 - } -} +extension CGFloat: ImportableAttributeType {} // MARK: - Data -extension Data: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Data { - - return Data() - } -} +extension Data: ImportableAttributeType {} // MARK: - Date @@ -127,114 +81,42 @@ extension Date: ImportableAttributeType {} // MARK: - Double -extension Double: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Double { - - return 0 - } -} +extension Double: ImportableAttributeType {} // MARK: - Float -extension Float: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Float { - - return 0 - } -} +extension Float: ImportableAttributeType {} // MARK: - Int -extension Int: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Int { - - return 0 - } -} +extension Int: ImportableAttributeType {} // MARK: - Int8 -extension Int8: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Int8 { - - return 0 - } -} +extension Int8: ImportableAttributeType {} // MARK: - Int16 -extension Int16: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Int16 { - - return 0 - } -} +extension Int16: ImportableAttributeType {} // MARK: - Int32 -extension Int32: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Int32 { - - return 0 - } -} +extension Int32: ImportableAttributeType {} // MARK: - Int64 -extension Int64: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> Int64 { - - return 0 - } -} +extension Int64: ImportableAttributeType {} // MARK: - NSData -extension NSData: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @nonobjc @inline(__always) - public class func cs_emptyValue() -> Self { - - return self.init() - } -} +extension NSData: ImportableAttributeType {} // MARK: - NSDate @@ -244,30 +126,12 @@ extension NSDate: ImportableAttributeType {} // MARK: - NSNumber -extension NSNumber: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @nonobjc @inline(__always) - public class func cs_emptyValue() -> Self { - - return self.init() - } -} +extension NSNumber: ImportableAttributeType {} // MARK: - NSString -extension NSString: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @nonobjc @inline(__always) - public class func cs_emptyValue() -> Self { - - return self.init() - } -} +extension NSString: ImportableAttributeType {} // MARK: - NSURL @@ -282,16 +146,7 @@ extension NSUUID: ImportableAttributeType {} // MARK: - String -extension String: ImportableAttributeType, EmptyableAttributeType { - - // MARK: EmptyableAttributeType - - @inline(__always) - public static func cs_emptyValue() -> String { - - return "" - } -} +extension String: ImportableAttributeType {} // MARK: - URL diff --git a/Sources/Relationship.swift b/Sources/Relationship.swift index 59807dd..7ea840d 100644 --- a/Sources/Relationship.swift +++ b/Sources/Relationship.swift @@ -97,8 +97,8 @@ public enum RelationshipContainer { public convenience init( _ keyPath: RawKeyPath, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -132,8 +132,8 @@ public enum RelationshipContainer { _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToOne, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -167,8 +167,8 @@ public enum RelationshipContainer { _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyOrdered, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -202,8 +202,8 @@ public enum RelationshipContainer { _ keyPath: RawKeyPath, inverse: @escaping (D) -> RelationshipContainer.ToManyUnordered, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -242,8 +242,8 @@ public enum RelationshipContainer { internal let minCount: Int = 0 internal let maxCount: Int = 1 internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) - internal let versionHashModifier: String? - internal let renamingIdentifier: String? + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? internal let affectedByKeyPaths: () -> Set internal weak var parentObject: CoreStoreObject? @@ -294,7 +294,7 @@ public enum RelationshipContainer { // MARK: Private - private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { + private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { self.keyPath = keyPath self.deleteRule = deleteRule.nativeValue @@ -345,8 +345,8 @@ public enum RelationshipContainer { minCount: Int = 0, maxCount: Int = 0, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -386,8 +386,8 @@ public enum RelationshipContainer { maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToOne, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -427,8 +427,8 @@ public enum RelationshipContainer { maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToManyOrdered, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -468,8 +468,8 @@ public enum RelationshipContainer { maxCount: Int = 0, inverse: @escaping (D) -> RelationshipContainer.ToManyUnordered, deleteRule: DeleteRule = .nullify, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -511,8 +511,8 @@ public enum RelationshipContainer { internal let minCount: Int internal let maxCount: Int internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) - internal let versionHashModifier: String? - internal let renamingIdentifier: String? + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? internal let affectedByKeyPaths: () -> Set internal weak var parentObject: CoreStoreObject? @@ -563,7 +563,7 @@ public enum RelationshipContainer { // MARK: Private - private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { + private init(keyPath: String, minCount: Int, maxCount: Int, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { self.keyPath = keyPath self.deleteRule = deleteRule.nativeValue @@ -619,8 +619,8 @@ public enum RelationshipContainer { deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -660,8 +660,8 @@ public enum RelationshipContainer { deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -701,8 +701,8 @@ public enum RelationshipContainer { deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -742,8 +742,8 @@ public enum RelationshipContainer { deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { self.init( @@ -785,8 +785,8 @@ public enum RelationshipContainer { internal let minCount: Int internal let maxCount: Int internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) - internal let versionHashModifier: String? - internal let renamingIdentifier: String? + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? internal let affectedByKeyPaths: () -> Set internal weak var parentObject: CoreStoreObject? @@ -837,7 +837,7 @@ public enum RelationshipContainer { // MARK: Private - private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { + private init(keyPath: RawKeyPath, inverseKeyPath: @escaping () -> RawKeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: @autoclosure @escaping () -> String?, renamingIdentifier: @autoclosure @escaping () -> String?, affectedByKeyPaths: @autoclosure @escaping () -> Set) { self.keyPath = keyPath self.deleteRule = deleteRule.nativeValue @@ -1204,21 +1204,3 @@ extension RelationshipContainer.ToManyUnordered { return relationship.nativeValue.isEqual(relationship2.nativeValue) } } - - -// MARK: - RelationshipProtocol - -internal protocol RelationshipProtocol: class { - - var keyPath: RawKeyPath { get } - var isToMany: Bool { get } - var isOrdered: Bool { get } - var deleteRule: NSDeleteRule { get } - var inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) { get } - var affectedByKeyPaths: () -> Set { get } - weak var parentObject: CoreStoreObject? { get set } - var versionHashModifier: String? { get } - var renamingIdentifier: String? { get } - var minCount: Int { get } - var maxCount: Int { get } -} diff --git a/Sources/RelationshipProtocol.swift b/Sources/RelationshipProtocol.swift new file mode 100644 index 0000000..de1ff88 --- /dev/null +++ b/Sources/RelationshipProtocol.swift @@ -0,0 +1,45 @@ +// +// RelationshipProtocol.swift +// CoreStore +// +// Copyright © 2017 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import Foundation +import CoreData + + +// MARK: - RelationshipProtocol + +internal protocol RelationshipProtocol: class { + + var keyPath: RawKeyPath { get } + var isToMany: Bool { get } + var isOrdered: Bool { get } + var deleteRule: NSDeleteRule { get } + var inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) { get } + var affectedByKeyPaths: () -> Set { get } + weak var parentObject: CoreStoreObject? { get set } + var versionHashModifier: () -> String? { get } + var renamingIdentifier: () -> String? { get } + var minCount: Int { get } + var maxCount: Int { get } +} diff --git a/Sources/Transformable.swift b/Sources/Transformable.swift new file mode 100644 index 0000000..167cc78 --- /dev/null +++ b/Sources/Transformable.swift @@ -0,0 +1,597 @@ +// +// Transformable.swift +// CoreStore +// +// Copyright © 2017 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import CoreData +import Foundation + + +// MARK: - DynamicObject + +public extension DynamicObject where Self: CoreStoreObject { + + /** + The containing type for transformable properties. `Transformable` properties support types that conforms to `NSCoding & NSCopying`. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let nickname = Value.Optional("nickname") + let color = Transformable.Optional("color") + } + ``` + - Important: `Transformable` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. + */ + public typealias Transformable = TransformableContainer +} + + +// MARK: - TransformableContainer + +/** + The containing type for transformable properties. Use the `DynamicObject.Transformable` typealias instead for shorter syntax. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let nickname = Value.Optional("nickname") + let color = Transformable.Optional("color") + } + ``` + */ +public enum TransformableContainer { + + // MARK: - Required + + /** + The containing type for transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let nickname = Value.Optional("nickname") + let color = Transformable.Optional("color") + } + ``` + - Important: `Transformable.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. + */ + public final class Required: AttributeProtocol { + + /** + Initializes the metadata for the property. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let color = Transformable.Required( + "color", + initial: UIColor.clear, + isTransient: true, + customGetter: Animal.getColor(_:) + ) + } + + private static func getColor(_ partialObject: PartialObject) -> UIColor { + let cachedColor = partialObject.primitiveValue(for: { $0.color }) + if cachedColor != UIColor.clear { + + return cachedColor + } + let color: UIColor + switch partialObject.value(for: { $0.species }) { + + case "Swift": color = UIColor.orange + case "Bulbasaur": color = UIColor.green + default: color = UIColor.black + } + partialObject.setPrimitiveValue(color, for: { $0.color }) + return color + } + ``` + - parameter keyPath: the permanent attribute name for this property. + - parameter initial: 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 properties 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 as an "override" for the default property getter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.primitiveValue(for:)` instead of `PartialObject.value(for:)`, which would unintentionally execute the same closure again recursively. + - parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.setPrimitiveValue(_:for:)` instead of `PartialObject.setValue(_:for:)`, which would unintentionally execute the same closure again recursively. + - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. + */ + public init( + _ keyPath: RawKeyPath, + initial: @autoclosure @escaping () -> V, + isIndexed: Bool = false, + isTransient: Bool = false, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, + customGetter: ((_ partialObject: PartialObject) -> V)? = nil, + customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, + affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { + + self.keyPath = keyPath + self.defaultValue = initial + self.isIndexed = isIndexed + self.isTransient = isTransient + self.versionHashModifier = versionHashModifier + self.renamingIdentifier = renamingIdentifier + self.customGetter = customGetter + self.customSetter = customSetter + self.affectedByKeyPaths = affectedByKeyPaths + } + + /** + The property value. + */ + public var value: V { + + get { + + CoreStore.assert( + self.parentObject != nil, + "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." + ) + return withExtendedLifetime(self.parentObject! as! O) { (object: O) in + + CoreStore.assert( + object.rawObject!.isRunningInAllowedQueue() == true, + "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." + ) + if let customGetter = self.customGetter { + + return customGetter(PartialObject(object.rawObject!)) + } + return object.rawObject!.value(forKey: self.keyPath)! as! V + } + } + set { + + CoreStore.assert( + self.parentObject != nil, + "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." + ) + return withExtendedLifetime(self.parentObject! as! O) { (object: O) in + + CoreStore.assert( + object.rawObject!.isRunningInAllowedQueue() == true, + "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." + ) + CoreStore.assert( + object.rawObject!.isEditableInContext() == true, + "Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction." + ) + if let customSetter = self.customSetter { + + return customSetter(PartialObject(object.rawObject!), newValue) + } + object.rawObject!.setValue( + newValue, + forKey: self.keyPath + ) + } + } + } + + + // MARK: AttributeProtocol + + internal static var attributeType: NSAttributeType { + + return .transformableAttributeType + } + + public let keyPath: RawKeyPath + + internal let isOptional = false + internal let isIndexed: Bool + internal let isTransient: Bool + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? + internal let defaultValue: () -> Any? + internal let affectedByKeyPaths: () -> Set + internal weak var parentObject: CoreStoreObject? + + internal private(set) lazy var getter: CoreStoreManagedObject.CustomGetter? = cs_lazy { [unowned self] in + + guard let customGetter = self.customGetter else { + + return nil + } + let keyPath = self.keyPath + return { (_ id: Any) -> Any? in + + let rawObject = id as! CoreStoreManagedObject + rawObject.willAccessValue(forKey: keyPath) + defer { + + rawObject.didAccessValue(forKey: keyPath) + } + let value = customGetter(PartialObject(rawObject)) + return value + } + } + + internal private(set) lazy var setter: CoreStoreManagedObject.CustomSetter? = cs_lazy { [unowned self] in + + guard let customSetter = self.customSetter else { + + return nil + } + let keyPath = self.keyPath + return { (_ id: Any, _ newValue: Any?) -> Void in + + let rawObject = id as! CoreStoreManagedObject + rawObject.willChangeValue(forKey: keyPath) + defer { + + rawObject.didChangeValue(forKey: keyPath) + } + customSetter( + PartialObject(rawObject), + newValue as! V + ) + } + } + + + // MARK: Private + + private let customGetter: ((_ partialObject: PartialObject) -> V)? + private let customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? + + + // MARK: Deprecated + + @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") + public convenience init( + _ keyPath: RawKeyPath, + `default`: @autoclosure @escaping () -> V, + isIndexed: Bool = false, + isTransient: Bool = false, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, + customGetter: ((_ partialObject: PartialObject) -> V)? = nil, + customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, + affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { + + self.init( + keyPath, + initial: `default`, + isIndexed: isIndexed, + isTransient: isTransient, + versionHashModifier: versionHashModifier, + renamingIdentifier: renamingIdentifier, + customGetter: customGetter, + customSetter: customSetter, + affectedByKeyPaths: affectedByKeyPaths + ) + } + } + + + // MARK: - Optional + + /** + The containing type for optional transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let nickname = Value.Optional("nickname") + let color = Transformable.Optional("color") + } + ``` + - Important: `Transformable.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. + */ + public final class Optional: AttributeProtocol { + + /** + Initializes the metadata for the property. + ``` + class Animal: CoreStoreObject { + let species = Value.Required("species") + let color = Transformable.Optional( + "color", + isTransient: true, + customGetter: Animal.getColor(_:) + ) + } + + private static func getColor(_ partialObject: PartialObject) -> UIColor? { + if let cachedColor = partialObject.primitiveValue(for: { $0.color }) { + return cachedColor + } + let color: UIColor? + switch partialObject.value(for: { $0.species }) { + + case "Swift": color = UIColor.orange + case "Bulbasaur": color = UIColor.green + default: return nil + } + partialObject.setPrimitiveValue(color, for: { $0.color }) + return color + } + ``` + - parameter keyPath: the permanent attribute name for this property. + - parameter initial: 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 properties 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 as an "override" for the default property getter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.primitiveValue(for:)` instead of `PartialObject.value(for:)`, which would unintentionally execute the same closure again recursively. + - parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.setPrimitiveValue(_:for:)` instead of `PartialObject.setValue(_:for:)`, which would unintentionally execute the same closure again recursively. + - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. + */ + public init( + _ keyPath: RawKeyPath, + initial: @autoclosure @escaping () -> V? = nil, + isIndexed: Bool = false, + isTransient: Bool = false, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, + customGetter: ((_ partialObject: PartialObject) -> V?)? = nil, + customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? = nil, + affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { + + self.keyPath = keyPath + self.defaultValue = initial + self.isIndexed = isIndexed + self.isTransient = isTransient + self.versionHashModifier = versionHashModifier + self.renamingIdentifier = renamingIdentifier + self.customGetter = customGetter + self.customSetter = customSetter + self.affectedByKeyPaths = affectedByKeyPaths + } + + /** + The property value. + */ + public var value: V? { + + get { + + CoreStore.assert( + self.parentObject != nil, + "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." + ) + return withExtendedLifetime(self.parentObject! as! O) { (object: O) in + + CoreStore.assert( + object.rawObject!.isRunningInAllowedQueue() == true, + "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." + ) + if let customGetter = self.customGetter { + + return customGetter(PartialObject(object.rawObject!)) + } + return object.rawObject!.value(forKey: self.keyPath) as! V? + } + } + set { + + CoreStore.assert( + self.parentObject != nil, + "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." + ) + return withExtendedLifetime(self.parentObject! as! O) { (object: O) in + + CoreStore.assert( + object.rawObject!.isRunningInAllowedQueue() == true, + "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." + ) + CoreStore.assert( + object.rawObject!.isEditableInContext() == true, + "Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction." + ) + if let customSetter = self.customSetter { + + return customSetter(PartialObject(object.rawObject!), newValue) + } + object.rawObject!.setValue( + newValue, + forKey: self.keyPath + ) + } + } + } + + + // MARK: AttributeProtocol + + internal static var attributeType: NSAttributeType { + + return .transformableAttributeType + } + + public let keyPath: RawKeyPath + + internal let isOptional = true + internal let isIndexed: Bool + internal let isTransient: Bool + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? + internal let defaultValue: () -> Any? + internal let affectedByKeyPaths: () -> Set + internal weak var parentObject: CoreStoreObject? + + internal private(set) lazy var getter: CoreStoreManagedObject.CustomGetter? = cs_lazy { [unowned self] in + + guard let customGetter = self.customGetter else { + + return nil + } + let keyPath = self.keyPath + return { (_ id: Any) -> Any? in + + let rawObject = id as! CoreStoreManagedObject + rawObject.willAccessValue(forKey: keyPath) + defer { + + rawObject.didAccessValue(forKey: keyPath) + } + let value = customGetter(PartialObject(rawObject)) + return value + } + } + + internal private(set) lazy var setter: CoreStoreManagedObject.CustomSetter? = cs_lazy { [unowned self] in + + guard let customSetter = self.customSetter else { + + return nil + } + let keyPath = self.keyPath + return { (_ id: Any, _ newValue: Any?) -> Void in + + let rawObject = id as! CoreStoreManagedObject + rawObject.willChangeValue(forKey: keyPath) + defer { + + rawObject.didChangeValue(forKey: keyPath) + } + customSetter( + PartialObject(rawObject), + newValue as! V? + ) + } + } + + + // MARK: Private + + private let customGetter: ((_ partialObject: PartialObject) -> V?)? + private let customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? + + + // MARK: Deprecated + + @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") + public convenience init( + _ keyPath: RawKeyPath, + `default`: @autoclosure @escaping () -> V? = nil, + isIndexed: Bool = false, + isTransient: Bool = false, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, + customGetter: ((_ partialObject: PartialObject) -> V?)? = nil, + customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? = nil, + affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { + + self.init( + keyPath, + initial: `default`, + isIndexed: isIndexed, + isTransient: isTransient, + versionHashModifier: versionHashModifier, + renamingIdentifier: renamingIdentifier, + customGetter: customGetter, + customSetter: customSetter, + affectedByKeyPaths: affectedByKeyPaths + ) + } + } +} + + +// MARK: - Operations + +infix operator .= : AssignmentPrecedence +infix operator .== : ComparisonPrecedence + +extension TransformableContainer.Required { + + /** + Assigns a transformable value to the property. The operation + ``` + animal.color .= UIColor.red + ``` + is equivalent to + ``` + animal.color.value = UIColor.red + ``` + */ + public static func .= (_ property: TransformableContainer.Required, _ newValue: V) { + + property.value = newValue + } + + /** + Assigns a transformable value from another property. The operation + ``` + animal.nickname .= anotherAnimal.species + ``` + is equivalent to + ``` + animal.nickname.value = anotherAnimal.species.value + ``` + */ + public static func .= (_ property: TransformableContainer.Required, _ property2: TransformableContainer.Required) { + + property.value = property2.value + } +} + +extension TransformableContainer.Optional { + + /** + Assigns an optional transformable value to the property. The operation + ``` + animal.color .= UIColor.red + ``` + is equivalent to + ``` + animal.color.value = UIColor.red + ``` + */ + public static func .= (_ property: TransformableContainer.Optional, _ newValue: V?) { + + property.value = newValue + } + + /** + Assigns an optional transformable value from another property. The operation + ``` + animal.color .= anotherAnimal.color + ``` + is equivalent to + ``` + animal.color.value = anotherAnimal.color.value + ``` + */ + public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Optional) { + + property.value = property2.value + } + + /** + Assigns a transformable value from another property. The operation + ``` + animal.color .= anotherAnimal.color + ``` + is equivalent to + ``` + animal.color.value = anotherAnimal.color.value + ``` + */ + public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Required) { + + property.value = property2.value + } +} diff --git a/Sources/Value.swift b/Sources/Value.swift index b7e8f4c..223ef45 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -43,19 +43,6 @@ public extension DynamicObject where Self: CoreStoreObject { - Important: `Value` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. */ public typealias Value = ValueContainer - - /** - The containing type for transformable properties. `Transformable` properties support types that conforms to `NSCoding & NSCopying`. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let nickname = Value.Optional("nickname") - let color = Transformable.Optional("color") - } - ``` - - Important: `Transformable` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. - */ - public typealias Transformable = TransformableContainer } @@ -86,13 +73,13 @@ public enum ValueContainer { ``` - Important: `Value.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. */ - public final class Required: AttributeProtocol where V.QueryableNativeType: CoreDataNativeType { + public final class Required: AttributeProtocol { /** Initializes the metadata for the property. ``` class Person: CoreStoreObject { - let title = Value.Required("title", default: "Mr.") + let title = Value.Required("title", initial: "Mr.") let name = Value.Required("name") let displayName = Value.Required( "displayName", @@ -114,7 +101,7 @@ public enum ValueContainer { } ``` - parameter keyPath: the permanent attribute name for this property. - - parameter default: the initial value for the property when the object is first created. For types that implement `EmptyableAttributeType`s, this argument may be omitted and the type's "empty" value will be used instead (e.g. `false` for `Bool`, `0` for `Int`, `""` for `String`, etc.) + - parameter initial: the initial value for the property when the object is first created - 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 properties are unchanged but the format or content of its data are changed.) @@ -125,11 +112,11 @@ public enum ValueContainer { */ public init( _ keyPath: RawKeyPath, - `default`: @autoclosure @escaping () -> V, + initial: @autoclosure @escaping () -> V, isIndexed: Bool = false, isTransient: Bool = false, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, customGetter: ((_ partialObject: PartialObject) -> V)? = nil, customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { @@ -137,7 +124,7 @@ public enum ValueContainer { self.keyPath = keyPath self.isIndexed = isIndexed self.isTransient = isTransient - self.defaultValue = { `default`().cs_toQueryableNativeType() } + self.defaultValue = { initial().cs_toQueryableNativeType() } self.versionHashModifier = versionHashModifier self.renamingIdentifier = renamingIdentifier self.customGetter = customGetter @@ -212,8 +199,8 @@ public enum ValueContainer { internal let isOptional = false internal let isIndexed: Bool internal let isTransient: Bool - internal let versionHashModifier: String? - internal let renamingIdentifier: String? + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? internal let defaultValue: () -> Any? internal let affectedByKeyPaths: () -> Set internal weak var parentObject: CoreStoreObject? @@ -265,6 +252,34 @@ public enum ValueContainer { private let customGetter: ((_ partialObject: PartialObject) -> V)? private let customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? + + + // MARK: Deprecated + + @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") + public convenience init( + _ keyPath: RawKeyPath, + `default`: @autoclosure @escaping () -> V, + isIndexed: Bool = false, + isTransient: Bool = false, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, + customGetter: ((_ partialObject: PartialObject) -> V)? = nil, + customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, + affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { + + self.init( + keyPath, + initial: `default`, + isIndexed: isIndexed, + isTransient: isTransient, + versionHashModifier: versionHashModifier, + renamingIdentifier: renamingIdentifier, + customGetter: customGetter, + customSetter: customSetter, + affectedByKeyPaths: affectedByKeyPaths + ) + } } @@ -281,13 +296,13 @@ public enum ValueContainer { ``` - Important: `Value.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. */ - public final class Optional: AttributeProtocol where V.QueryableNativeType: CoreDataNativeType { + public final class Optional: AttributeProtocol { /** Initializes the metadata for the property. ``` class Person: CoreStoreObject { - let title = Value.Optional("title", default: "Mr.") + let title = Value.Optional("title", initial: "Mr.") let name = Value.Optional("name") let displayName = Value.Optional( "displayName", @@ -308,7 +323,7 @@ public enum ValueContainer { } ``` - parameter keyPath: the permanent attribute name for this property. - - parameter default: the initial value for the property when the object is first created. Defaults to `nil` if not specified. + - parameter initial: 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 properties are unchanged but the format or content of its data are changed.) @@ -324,11 +339,11 @@ public enum ValueContainer { */ public init( _ keyPath: RawKeyPath, - `default`: @autoclosure @escaping () -> V? = nil, + initial: @autoclosure @escaping () -> V? = nil, isIndexed: Bool = false, isTransient: Bool = false, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, customGetter: ((_ partialObject: PartialObject) -> V?)? = nil, customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { @@ -336,7 +351,7 @@ public enum ValueContainer { self.keyPath = keyPath self.isIndexed = isIndexed self.isTransient = isTransient - self.defaultValue = { `default`()?.cs_toQueryableNativeType() } + self.defaultValue = { initial()?.cs_toQueryableNativeType() } self.versionHashModifier = versionHashModifier self.renamingIdentifier = renamingIdentifier self.customGetter = customGetter @@ -409,8 +424,8 @@ public enum ValueContainer { internal let isOptional = true internal let isIndexed: Bool internal let isTransient: Bool - internal let versionHashModifier: String? - internal let renamingIdentifier: String? + internal let versionHashModifier: () -> String? + internal let renamingIdentifier: () -> String? internal let defaultValue: () -> Any? internal let affectedByKeyPaths: () -> Set internal weak var parentObject: CoreStoreObject? @@ -462,457 +477,34 @@ public enum ValueContainer { private let customGetter: ((_ partialObject: PartialObject) -> V?)? private let customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? - } -} - -public extension ValueContainer.Required where V: EmptyableAttributeType { - - /** - Initializes the metadata for the property. This convenience initializer uses the `EmptyableAttributeType`'s "empty" value as the initial value for the property when the object is first created (e.g. `false` for `Bool`, `0` for `Int`, `""` for `String`, etc.) - ``` - class Person: CoreStoreObject { - let title = Value.Required("title", default: "Mr.") // explicit default value - let name = Value.Required("name") // initial value defaults to empty string - } - ``` - - parameter keyPath: the permanent attribute name for this property. - - 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 properties 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 as an "override" for the default property getter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.primitiveValue(for:)` instead of `PartialObject.value(for:)`, which would unintentionally execute the same closure again recursively. - - parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.setPrimitiveValue(_:for:)` instead of `PartialObject.setValue(_:for:)`, which would unintentionally execute the same closure again recursively. - - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. - */ - public convenience init( - _ keyPath: RawKeyPath, - isIndexed: Bool = false, - isTransient: Bool = false, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, - customGetter: ((_ partialObject: PartialObject) -> V)? = nil, - customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, - affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { - - self.init( - keyPath, - default: V.cs_emptyValue(), - isIndexed: isIndexed, - isTransient: isTransient, - versionHashModifier: versionHashModifier, - renamingIdentifier: renamingIdentifier, - customGetter: customGetter, - customSetter: customSetter, - affectedByKeyPaths: affectedByKeyPaths - ) - } -} - - -// MARK: - TransformableContainer - -/** - The containing type for transformable properties. Use the `DynamicObject.Transformable` typealias instead for shorter syntax. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let nickname = Value.Optional("nickname") - let color = Transformable.Optional("color") - } - ``` - */ -public enum TransformableContainer { - - // MARK: - Required - - /** - The containing type for transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let nickname = Value.Optional("nickname") - let color = Transformable.Optional("color") - } - ``` - - Important: `Transformable.Required` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. - */ - public final class Required: AttributeProtocol { - - /** - Initializes the metadata for the property. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let color = Transformable.Required( - "color", - default: UIColor.clear, - isTransient: true, - customGetter: Animal.getColor(_:) - ) - } - - private static func getColor(_ partialObject: PartialObject) -> UIColor { - let cachedColor = partialObject.primitiveValue(for: { $0.color }) - if cachedColor != UIColor.clear { - - return cachedColor - } - let color: UIColor - switch partialObject.value(for: { $0.species }) { - - case "Swift": color = UIColor.orange - case "Bulbasaur": color = UIColor.green - default: color = UIColor.black - } - partialObject.setPrimitiveValue(color, for: { $0.color }) - return color - } - ``` - - parameter keyPath: the permanent attribute name for this property. - - 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 properties 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 as an "override" for the default property getter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.primitiveValue(for:)` instead of `PartialObject.value(for:)`, which would unintentionally execute the same closure again recursively. - - parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.setPrimitiveValue(_:for:)` instead of `PartialObject.setValue(_:for:)`, which would unintentionally execute the same closure again recursively. - - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. - */ - public init( - _ keyPath: RawKeyPath, - `default`: @autoclosure @escaping () -> V, - isIndexed: Bool = false, - isTransient: Bool = false, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, - customGetter: ((_ partialObject: PartialObject) -> V)? = nil, - customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? = nil, - affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { - - self.keyPath = keyPath - self.defaultValue = `default` - self.isIndexed = isIndexed - self.isTransient = isTransient - self.versionHashModifier = versionHashModifier - self.renamingIdentifier = renamingIdentifier - self.customGetter = customGetter - self.customSetter = customSetter - self.affectedByKeyPaths = affectedByKeyPaths - } - - /** - The property value. - */ - public var value: V { - - get { - - CoreStore.assert( - self.parentObject != nil, - "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." - ) - return withExtendedLifetime(self.parentObject! as! O) { (object: O) in - - CoreStore.assert( - object.rawObject!.isRunningInAllowedQueue() == true, - "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." - ) - if let customGetter = self.customGetter { - - return customGetter(PartialObject(object.rawObject!)) - } - return object.rawObject!.value(forKey: self.keyPath)! as! V - } - } - set { - - CoreStore.assert( - self.parentObject != nil, - "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." - ) - return withExtendedLifetime(self.parentObject! as! O) { (object: O) in - - CoreStore.assert( - object.rawObject!.isRunningInAllowedQueue() == true, - "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." - ) - CoreStore.assert( - object.rawObject!.isEditableInContext() == true, - "Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction." - ) - if let customSetter = self.customSetter { - - return customSetter(PartialObject(object.rawObject!), newValue) - } - object.rawObject!.setValue( - newValue, - forKey: self.keyPath - ) - } - } - } - // MARK: AttributeProtocol + // MARK: Deprecated - internal static var attributeType: NSAttributeType { - - return .transformableAttributeType - } - - public let keyPath: RawKeyPath - - internal let isOptional = false - internal let isIndexed: Bool - internal let isTransient: Bool - internal let versionHashModifier: String? - internal let renamingIdentifier: String? - internal let defaultValue: () -> Any? - internal let affectedByKeyPaths: () -> Set - internal weak var parentObject: CoreStoreObject? - - internal private(set) lazy var getter: CoreStoreManagedObject.CustomGetter? = cs_lazy { [unowned self] in - - guard let customGetter = self.customGetter else { - - return nil - } - let keyPath = self.keyPath - return { (_ id: Any) -> Any? in - - let rawObject = id as! CoreStoreManagedObject - rawObject.willAccessValue(forKey: keyPath) - defer { - - rawObject.didAccessValue(forKey: keyPath) - } - let value = customGetter(PartialObject(rawObject)) - return value - } - } - - internal private(set) lazy var setter: CoreStoreManagedObject.CustomSetter? = cs_lazy { [unowned self] in - - guard let customSetter = self.customSetter else { - - return nil - } - let keyPath = self.keyPath - return { (_ id: Any, _ newValue: Any?) -> Void in - - let rawObject = id as! CoreStoreManagedObject - rawObject.willChangeValue(forKey: keyPath) - defer { - - rawObject.didChangeValue(forKey: keyPath) - } - customSetter( - PartialObject(rawObject), - newValue as! V - ) - } - } - - - // MARK: Private - - private let customGetter: ((_ partialObject: PartialObject) -> V)? - private let customSetter: ((_ partialObject: PartialObject, _ newValue: V) -> Void)? - } - - - // MARK: - Optional - - /** - The containing type for optional transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let nickname = Value.Optional("nickname") - let color = Transformable.Optional("color") - } - ``` - - Important: `Transformable.Optional` properties are required to be stored properties. Computed properties will be ignored, including `lazy` and `weak` properties. - */ - public final class Optional: AttributeProtocol { - - /** - Initializes the metadata for the property. - ``` - class Animal: CoreStoreObject { - let species = Value.Required("species") - let color = Transformable.Optional( - "color", - isTransient: true, - customGetter: Animal.getColor(_:) - ) - } - - private static func getColor(_ partialObject: PartialObject) -> UIColor? { - if let cachedColor = partialObject.primitiveValue(for: { $0.color }) { - return cachedColor - } - let color: UIColor? - switch partialObject.value(for: { $0.species }) { - - case "Swift": color = UIColor.orange - case "Bulbasaur": color = UIColor.green - default: return nil - } - partialObject.setPrimitiveValue(color, for: { $0.color }) - return color - } - ``` - - parameter keyPath: the permanent attribute name for this property. - - 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 properties 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 as an "override" for the default property getter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.primitiveValue(for:)` instead of `PartialObject.value(for:)`, which would unintentionally execute the same closure again recursively. - - parameter customSetter: use this closure as an "override" for the default property setter. The closure receives a `PartialObject`, which acts as a fast, type-safe KVC interface for `CoreStoreObject`. The reason a `CoreStoreObject` instance is not passed directly is because the Core Data runtime is not aware of `CoreStoreObject` properties' static typing, and so loading those info everytime KVO invokes this accessor method incurs a cumulative performance hit (especially in KVO-heavy operations such as `ListMonitor` observing.) When accessing the property value from `PartialObject`, make sure to use `PartialObject.setPrimitiveValue(_:for:)` instead of `PartialObject.setValue(_:for:)`, which would unintentionally execute the same closure again recursively. - - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. - */ - public init( + @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") + public convenience init( _ keyPath: RawKeyPath, `default`: @autoclosure @escaping () -> V? = nil, isIndexed: Bool = false, isTransient: Bool = false, - versionHashModifier: String? = nil, - renamingIdentifier: String? = nil, + versionHashModifier: @autoclosure @escaping () -> String? = nil, + renamingIdentifier: @autoclosure @escaping () -> String? = nil, customGetter: ((_ partialObject: PartialObject) -> V?)? = nil, customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? = nil, affectedByKeyPaths: @autoclosure @escaping () -> Set = []) { - self.keyPath = keyPath - self.defaultValue = `default` - self.isIndexed = isIndexed - self.isTransient = isTransient - self.versionHashModifier = versionHashModifier - self.renamingIdentifier = renamingIdentifier - self.customGetter = customGetter - self.customSetter = customSetter - self.affectedByKeyPaths = affectedByKeyPaths + self.init( + keyPath, + initial: `default`, + isIndexed: isIndexed, + isTransient: isTransient, + versionHashModifier: versionHashModifier, + renamingIdentifier: renamingIdentifier, + customGetter: customGetter, + customSetter: customSetter, + affectedByKeyPaths: affectedByKeyPaths + ) } - - /** - The property value. - */ - public var value: V? { - - get { - - CoreStore.assert( - self.parentObject != nil, - "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." - ) - return withExtendedLifetime(self.parentObject! as! O) { (object: O) in - - CoreStore.assert( - object.rawObject!.isRunningInAllowedQueue() == true, - "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." - ) - if let customGetter = self.customGetter { - - return customGetter(PartialObject(object.rawObject!)) - } - return object.rawObject!.value(forKey: self.keyPath) as! V? - } - } - set { - - CoreStore.assert( - self.parentObject != nil, - "Attempted to access values from a \(cs_typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types." - ) - return withExtendedLifetime(self.parentObject! as! O) { (object: O) in - - CoreStore.assert( - object.rawObject!.isRunningInAllowedQueue() == true, - "Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue." - ) - CoreStore.assert( - object.rawObject!.isEditableInContext() == true, - "Attempted to update a \(cs_typeName(O.self))'s value from outside a transaction." - ) - if let customSetter = self.customSetter { - - return customSetter(PartialObject(object.rawObject!), newValue) - } - object.rawObject!.setValue( - newValue, - forKey: self.keyPath - ) - } - } - } - - - // MARK: AttributeProtocol - - internal static var attributeType: NSAttributeType { - - return .transformableAttributeType - } - - public let keyPath: RawKeyPath - - internal let isOptional = true - internal let isIndexed: Bool - internal let isTransient: Bool - internal let versionHashModifier: String? - internal let renamingIdentifier: String? - internal let defaultValue: () -> Any? - internal let affectedByKeyPaths: () -> Set - internal weak var parentObject: CoreStoreObject? - - internal private(set) lazy var getter: CoreStoreManagedObject.CustomGetter? = cs_lazy { [unowned self] in - - guard let customGetter = self.customGetter else { - - return nil - } - let keyPath = self.keyPath - return { (_ id: Any) -> Any? in - - let rawObject = id as! CoreStoreManagedObject - rawObject.willAccessValue(forKey: keyPath) - defer { - - rawObject.didAccessValue(forKey: keyPath) - } - let value = customGetter(PartialObject(rawObject)) - return value - } - } - - internal private(set) lazy var setter: CoreStoreManagedObject.CustomSetter? = cs_lazy { [unowned self] in - - guard let customSetter = self.customSetter else { - - return nil - } - let keyPath = self.keyPath - return { (_ id: Any, _ newValue: Any?) -> Void in - - let rawObject = id as! CoreStoreManagedObject - rawObject.willChangeValue(forKey: keyPath) - defer { - - rawObject.didChangeValue(forKey: keyPath) - } - customSetter( - PartialObject(rawObject), - newValue as! V? - ) - } - } - - - // MARK: Private - - private let customGetter: ((_ partialObject: PartialObject) -> V?)? - private let customSetter: ((_ partialObject: PartialObject, _ newValue: V?) -> Void)? } } @@ -1122,104 +714,3 @@ extension ValueContainer.Optional { return property.value == property2.value } } - -extension TransformableContainer.Required { - - /** - Assigns a transformable value to the property. The operation - ``` - animal.color .= UIColor.red - ``` - is equivalent to - ``` - animal.color.value = UIColor.red - ``` - */ - public static func .= (_ property: TransformableContainer.Required, _ newValue: V) { - - property.value = newValue - } - - /** - Assigns a transformable value from another property. The operation - ``` - animal.nickname .= anotherAnimal.species - ``` - is equivalent to - ``` - animal.nickname.value = anotherAnimal.species.value - ``` - */ - public static func .= (_ property: TransformableContainer.Required, _ property2: TransformableContainer.Required) { - - property.value = property2.value - } -} - -extension TransformableContainer.Optional { - - /** - Assigns an optional transformable value to the property. The operation - ``` - animal.color .= UIColor.red - ``` - is equivalent to - ``` - animal.color.value = UIColor.red - ``` - */ - public static func .= (_ property: TransformableContainer.Optional, _ newValue: V?) { - - property.value = newValue - } - - /** - Assigns an optional transformable value from another property. The operation - ``` - animal.color .= anotherAnimal.color - ``` - is equivalent to - ``` - animal.color.value = anotherAnimal.color.value - ``` - */ - public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Optional) { - - property.value = property2.value - } - - /** - Assigns a transformable value from another property. The operation - ``` - animal.color .= anotherAnimal.color - ``` - is equivalent to - ``` - animal.color.value = anotherAnimal.color.value - ``` - */ - public static func .= (_ property: TransformableContainer.Optional, _ property2: TransformableContainer.Required) { - - property.value = property2.value - } -} - - -// MARK: - AttributeProtocol - -internal protocol AttributeProtocol: class { - - static var attributeType: NSAttributeType { get } - - var keyPath: RawKeyPath { get } - var isOptional: Bool { get } - var isIndexed: Bool { get } - var isTransient: Bool { get } - var versionHashModifier: String? { get } - var renamingIdentifier: String? { get } - var defaultValue: () -> Any? { get } - var affectedByKeyPaths: () -> Set { get } - weak var parentObject: CoreStoreObject? { get set } - var getter: CoreStoreManagedObject.CustomGetter? { get } - var setter: CoreStoreManagedObject.CustomSetter? { get } -} From 10ccadd96c84b5763ade7a78128a6269ccd22954 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Sat, 5 Aug 2017 08:25:03 +0900 Subject: [PATCH 06/17] update demo app --- .../List and Object Observers Demo/Palette.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift index dfa1b36..31f93ed 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift @@ -16,9 +16,9 @@ import CoreStore final class Palette: CoreStoreObject { - let hue = Value.Required("hue") - let saturation = Value.Required("saturation") - let brightness = Value.Required("brightness") + let hue = Value.Required("hue", initial: 0) + let saturation = Value.Required("saturation", initial: 0) + let brightness = Value.Required("brightness", initial: 0) let colorName = Value.Optional( "colorName", From f36cb8af6358a8bcfc3a745a186a00eb5884af50 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Sat, 5 Aug 2017 08:25:28 +0900 Subject: [PATCH 07/17] iOS 11 fixed the NSFetchRequest.affectedStores bug --- Sources/CoreStoreBridge.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/CoreStoreBridge.m b/Sources/CoreStoreBridge.m index 2ded9b0..82763b2 100644 --- a/Sources/CoreStoreBridge.m +++ b/Sources/CoreStoreBridge.m @@ -235,15 +235,16 @@ CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RE - (void)setAffectedStores:(NSArray *_Nullable)affectedStores { - // Bugfix for NSFetchRequest messing up memory management for `affectedStores` - // http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified - - if (NSFoundationVersionNumber < NSFoundationVersionNumber10_0) { + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + if ([processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 11, 0, 0 }] + || ![processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 10, 0, 0 }]) { self.safeAffectedStores = affectedStores; [super setAffectedStores:affectedStores]; return; } + // Bugfix for NSFetchRequest messing up memory management for `affectedStores` + // http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified if (self.releaseArray != NULL) { CFRelease(self.releaseArray); From 74c64619c3c9e16e017d5e926efae95cb0133398 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Tue, 8 Aug 2017 07:56:21 +0900 Subject: [PATCH 08/17] Fix compile error for Xcode 9 beta 5 --- Sources/XcodeDataModelSchema.swift | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Sources/XcodeDataModelSchema.swift b/Sources/XcodeDataModelSchema.swift index e4db7ff..19a9819 100644 --- a/Sources/XcodeDataModelSchema.swift +++ b/Sources/XcodeDataModelSchema.swift @@ -145,7 +145,7 @@ public final class XcodeDataModelSchema: DynamicSchema { public required init(modelName: ModelVersion, modelVersionFileURL: URL) { CoreStore.assert( - NSManagedObjectModel(contentsOf: modelVersionFileURL) != nil, + FileManager.default.fileExists(atPath: modelVersionFileURL.path), "Could not find the \"\(modelName).mom\" version file for the model at URL \"\(modelVersionFileURL)\"." ) @@ -164,12 +164,13 @@ public final class XcodeDataModelSchema: DynamicSchema { return cachedRawModel } - if let rawModel = NSManagedObjectModel(contentsOf: self.modelVersionFileURL) { - - self.cachedRawModel = rawModel - return rawModel - } - CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(self.modelVersionFileURL)\".") + CoreStore.assert( + FileManager.default.fileExists(atPath: self.modelVersionFileURL.path), + "Could not find the \"\(self.modelVersion).mom\" version file for the model at URL \"\(self.modelVersionFileURL)\"." + ) + let rawModel = NSManagedObjectModel(contentsOf: self.modelVersionFileURL) + self.cachedRawModel = rawModel + return rawModel } From 8bac4aa901cc804f4aa4bf2cb5354e82e2121bb3 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Wed, 23 Aug 2017 18:40:06 +0900 Subject: [PATCH 09/17] Fixed Xcode 9 beta 6 errors --- Sources/XcodeDataModelSchema.swift | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Sources/XcodeDataModelSchema.swift b/Sources/XcodeDataModelSchema.swift index 19a9819..e4db7ff 100644 --- a/Sources/XcodeDataModelSchema.swift +++ b/Sources/XcodeDataModelSchema.swift @@ -145,7 +145,7 @@ public final class XcodeDataModelSchema: DynamicSchema { public required init(modelName: ModelVersion, modelVersionFileURL: URL) { CoreStore.assert( - FileManager.default.fileExists(atPath: modelVersionFileURL.path), + NSManagedObjectModel(contentsOf: modelVersionFileURL) != nil, "Could not find the \"\(modelName).mom\" version file for the model at URL \"\(modelVersionFileURL)\"." ) @@ -164,13 +164,12 @@ public final class XcodeDataModelSchema: DynamicSchema { return cachedRawModel } - CoreStore.assert( - FileManager.default.fileExists(atPath: self.modelVersionFileURL.path), - "Could not find the \"\(self.modelVersion).mom\" version file for the model at URL \"\(self.modelVersionFileURL)\"." - ) - let rawModel = NSManagedObjectModel(contentsOf: self.modelVersionFileURL) - self.cachedRawModel = rawModel - return rawModel + if let rawModel = NSManagedObjectModel(contentsOf: self.modelVersionFileURL) { + + self.cachedRawModel = rawModel + return rawModel + } + CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(self.modelVersionFileURL)\".") } From 53100b202d63b0ce44c2ab7d34b8674a9419a708 Mon Sep 17 00:00:00 2001 From: Jannon Frank Date: Thu, 21 Sep 2017 11:38:29 -0700 Subject: [PATCH 10/17] add case-insensitive sortkeys --- Sources/OrderBy.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Sources/OrderBy.swift b/Sources/OrderBy.swift index 862dbda..fb7d5af 100644 --- a/Sources/OrderBy.swift +++ b/Sources/OrderBy.swift @@ -48,6 +48,16 @@ public enum SortKey { Indicates that the `RawKeyPath` should be sorted in descending order */ case descending(RawKeyPath) + + /** + Indicates that the `RawKeyPath` should be sorted in ascending order in a case-insenstive manner + */ + case ascendingInsensitive(RawKeyPath) + + /** + Indicates that the `RawKeyPath` should be sorted in descending order in a case-insenstive manner + */ + case descendingInsensitive(RawKeyPath) } @@ -124,6 +134,12 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable { case .descending(let keyPath): return NSSortDescriptor(key: keyPath, ascending: false) + + case .ascendingInsensitive(let keyPath): + return NSSortDescriptor(key: keyPath, ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:))) + + case .descendingInsensitive(let keyPath): + return NSSortDescriptor(key: keyPath, ascending: false, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:))) } } ) From be5da632b314500fc258ed68652894c84df0fa70 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Fri, 22 Sep 2017 23:18:25 +0900 Subject: [PATCH 11/17] fix segmentation fault --- Sources/DynamicObject.swift | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Sources/DynamicObject.swift b/Sources/DynamicObject.swift index c48bdba..b36c020 100644 --- a/Sources/DynamicObject.swift +++ b/Sources/DynamicObject.swift @@ -78,12 +78,7 @@ extension NSManagedObject: DynamicObject { public class func cs_fromRaw(object: NSManagedObject) -> Self { - @inline(__always) - func forceCast(_ value: Any) -> T { - - return value as! T - } - return forceCast(object) + return unsafeDowncast(object, to: self) } public static func cs_matches(object: NSManagedObject) -> Bool { @@ -124,12 +119,7 @@ extension CoreStoreObject { if let coreStoreObject = object.coreStoreObject { - @inline(__always) - func forceCast(_ value: CoreStoreObject) -> T { - - return value as! T - } - return forceCast(coreStoreObject) + return unsafeDowncast(coreStoreObject, to: self) } let coreStoreObject = self.init(rawObject: object) object.coreStoreObject = coreStoreObject From b4117eeb028facf83fee0828882d84fb9c1c354d Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Wed, 11 Oct 2017 07:50:24 +0900 Subject: [PATCH 12/17] updated documentation (fixes #198) --- README.md | 6 +- Sources/CoreStoreLogger.swift | 13 -- Sources/CoreStoreObject.swift | 7 +- Sources/CoreStoreSchema.swift | 12 +- Sources/DataStack.swift | 10 -- Sources/DefaultLogger.swift | 6 - Sources/Entity.swift | 4 +- Sources/ICloudStore.swift | 2 - Sources/NSManagedObject+Logging.swift | 208 -------------------------- Sources/PartialObject.swift | 67 +++++++++ Sources/SQLiteStore.swift | 2 - Sources/Transformable.swift | 16 +- Sources/Value.swift | 11 +- Sources/VersionLock.swift | 4 +- 14 files changed, 99 insertions(+), 269 deletions(-) diff --git a/README.md b/README.md index 7284f6e..38c4ab5 100644 --- a/README.md +++ b/README.md @@ -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. ```swift class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") } class Dog: Animal { @@ -1684,14 +1684,14 @@ class Dog: Animal { } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pets = Relationship.ToManyUnordered("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: ```swift class Person: CoreStoreObject { - private let _name = Value.Required("name") + private let _name = Value.Required("name", initial: "") // ... } ``` diff --git a/Sources/CoreStoreLogger.swift b/Sources/CoreStoreLogger.swift index 1f6832f..57e1714 100644 --- a/Sources/CoreStoreLogger.swift +++ b/Sources/CoreStoreLogger.swift @@ -47,12 +47,6 @@ public enum LogLevel { */ 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. @@ -100,13 +94,6 @@ public protocol 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) { Swift.fatalError(message, file: fileName, line: UInt(lineNumber)) diff --git a/Sources/CoreStoreObject.swift b/Sources/CoreStoreObject.swift index 2ec6c4c..ec2aa7b 100644 --- a/Sources/CoreStoreObject.swift +++ b/Sources/CoreStoreObject.swift @@ -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`, `Value.Optional` for values, or `Relationship.ToOne`, `Relationship.ToManyOrdered`, `Relationship.ToManyUnordered` for relationships. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let master = Relationship.ToOne("master") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pet = Relationship.ToOne("pet", inverse: { $0.master }) } ``` @@ -141,6 +141,9 @@ open /*abstract*/ class CoreStoreObject: DynamicObject, Hashable { 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 { CoreStore.assert( diff --git a/Sources/CoreStoreSchema.swift b/Sources/CoreStoreSchema.swift index c685d6b..82a0713 100644 --- a/Sources/CoreStoreSchema.swift +++ b/Sources/CoreStoreSchema.swift @@ -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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let master = Relationship.ToOne("master") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pet = Relationship.ToOne("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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let master = Relationship.ToOne("master") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pet = Relationship.ToOne("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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") } CoreStore.defaultStack = DataStack( diff --git a/Sources/DataStack.swift b/Sources/DataStack.swift index 726ffb6..7187306 100644 --- a/Sources/DataStack.swift +++ b/Sources/DataStack.swift @@ -105,9 +105,6 @@ public final class DataStack: Equatable { */ public required init(schemaHistory: SchemaHistory) { - // TODO: test before release (rolled back) -// _ = DataStack.isGloballyInitialized - self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel) self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator) self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext) @@ -585,13 +582,6 @@ public final class DataStack: Equatable { // 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 finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set]() diff --git a/Sources/DefaultLogger.swift b/Sources/DefaultLogger.swift index 380fdf5..fcfc486 100644 --- a/Sources/DefaultLogger.swift +++ b/Sources/DefaultLogger.swift @@ -33,12 +33,6 @@ import Foundation */ 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`. */ diff --git a/Sources/Entity.swift b/Sources/Entity.swift index bb6fc26..33da35f 100644 --- a/Sources/Entity.swift +++ b/Sources/Entity.swift @@ -34,13 +34,13 @@ import ObjectiveC The `Entity` contains `NSEntityDescription` metadata for `CoreStoreObject` subclasses. Pass the `Entity` instances to `CoreStoreSchema` initializer. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let master = Relationship.ToOne("master") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pet = Relationship.ToOne("pet", inverse: { $0.master }) } diff --git a/Sources/ICloudStore.swift b/Sources/ICloudStore.swift index ba96b6b..edf42f5 100644 --- a/Sources/ICloudStore.swift +++ b/Sources/ICloudStore.swift @@ -425,8 +425,6 @@ public final class ICloudStore: CloudStorage { */ public func cs_eraseStorageAndWait(soureModel: NSManagedObjectModel) throws { - // TODO: check if attached to persistent store - let cacheFileURL = self.cacheFileURL try autoreleasepool { diff --git a/Sources/NSManagedObject+Logging.swift b/Sources/NSManagedObject+Logging.swift index 2db850f..47847dd 100644 --- a/Sources/NSManagedObject+Logging.swift +++ b/Sources/NSManagedObject+Logging.swift @@ -66,212 +66,4 @@ internal extension NSManagedObject { } 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) { -// -// 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 -// } -// } } diff --git a/Sources/PartialObject.swift b/Sources/PartialObject.swift index 54c1742..eaabcca 100644 --- a/Sources/PartialObject.swift +++ b/Sources/PartialObject.swift @@ -34,6 +34,9 @@ import Foundation */ public struct PartialObject { + /** + Returns a the actual `CoreStoreObject` instance for the receiver. + */ public func completeObject() -> O { return O.cs_fromRaw(object: self.rawObject) @@ -42,6 +45,9 @@ public struct PartialObject { // MARK: Value.Required accessors/mutators + /** + Returns the value for the property identified by a given key. + */ public func value(for property: (O) -> ValueContainer.Required) -> V { return V.cs_fromQueryableNativeType( @@ -49,6 +55,9 @@ public struct PartialObject { )! } + /** + Sets the property of the receiver specified by a given key to a given value. + */ public func setValue(_ value: V, for property: (O) -> ValueContainer.Required) { self.rawObject.setValue( @@ -57,6 +66,11 @@ public struct PartialObject { ) } + /** + 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(for property: (O) -> ValueContainer.Required) -> V { return V.cs_fromQueryableNativeType( @@ -64,6 +78,11 @@ public struct PartialObject { )! } + /** + 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(_ value: V, for property: (O) -> ValueContainer.Required) { self.rawObject.setPrimitiveValue( @@ -75,12 +94,18 @@ public struct PartialObject { // MARK: Value.Optional utilities + /** + Returns the value for the property identified by a given key. + */ public func value(for property: (O) -> ValueContainer.Optional) -> V? { return (self.rawObject.value(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?) .flatMap(V.cs_fromQueryableNativeType) } + /** + Sets the property of the receiver specified by a given key to a given value. + */ public func setValue(_ value: V?, for property: (O) -> ValueContainer.Optional) { self.rawObject.setValue( @@ -89,12 +114,22 @@ public struct PartialObject { ) } + /** + 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(for property: (O) -> ValueContainer.Optional) -> V? { return (self.rawObject.primitiveValue(forKey: property(O.meta).keyPath) as! V.QueryableNativeType?) .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(_ value: V?, for property: (O) -> ValueContainer.Optional) { self.rawObject.setPrimitiveValue( @@ -106,11 +141,17 @@ public struct PartialObject { // MARK: Transformable.Required utilities + /** + Returns the value for the property identified by a given key. + */ public func value(for property: (O) -> TransformableContainer.Required) -> 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(_ value: V, for property: (O) -> TransformableContainer.Required) { self.rawObject.setValue( @@ -119,11 +160,21 @@ public struct PartialObject { ) } + /** + 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(for property: (O) -> TransformableContainer.Required) -> 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(_ value: V, for property: (O) -> TransformableContainer.Required) { self.rawObject.setPrimitiveValue( @@ -135,11 +186,17 @@ public struct PartialObject { // MARK: Transformable.Optional utilities + /** + Returns the value for the property identified by a given key. + */ public func value(for property: (O) -> TransformableContainer.Optional) -> 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(_ value: V?, for property: (O) -> TransformableContainer.Optional) { self.rawObject.setValue( @@ -148,11 +205,21 @@ public struct PartialObject { ) } + /** + 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(for property: (O) -> TransformableContainer.Optional) -> 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(_ value: V?, for property: (O) -> TransformableContainer.Optional) { self.rawObject.setPrimitiveValue( diff --git a/Sources/SQLiteStore.swift b/Sources/SQLiteStore.swift index b50c29f..be95dfb 100644 --- a/Sources/SQLiteStore.swift +++ b/Sources/SQLiteStore.swift @@ -226,8 +226,6 @@ public final class SQLiteStore: LocalStorage { */ public func cs_eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws { - // TODO: check if attached to persistent store - func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws { let fileManager = FileManager.default diff --git a/Sources/Transformable.swift b/Sources/Transformable.swift index 167cc78..a771331 100644 --- a/Sources/Transformable.swift +++ b/Sources/Transformable.swift @@ -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`. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") - let nickname = Value.Optional("nickname") - let color = Transformable.Optional("color") + let species = Value.Required("species", initial: "") + let nickname = Value.Optional("nickname") + let color = Transformable.Optional("color") } ``` - 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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } @@ -66,7 +66,7 @@ public enum TransformableContainer { The containing type for transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } @@ -79,7 +79,7 @@ public enum TransformableContainer { Initializes the metadata for the property. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let color = Transformable.Required( "color", initial: UIColor.clear, @@ -292,7 +292,7 @@ public enum TransformableContainer { The containing type for optional transformable properties. Any type that conforms to `NSCoding & NSCopying` are supported. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } @@ -305,7 +305,7 @@ public enum TransformableContainer { Initializes the metadata for the property. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let color = Transformable.Optional( "color", isTransient: true, diff --git a/Sources/Value.swift b/Sources/Value.swift index 223ef45..e3d725b 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -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`. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } @@ -66,7 +66,7 @@ public enum ValueContainer { The containing type for required value properties. Any type that conforms to `ImportableAttributeType` are supported. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } @@ -80,9 +80,10 @@ public enum ValueContainer { ``` class Person: CoreStoreObject { let title = Value.Required("title", initial: "Mr.") - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let displayName = Value.Required( "displayName", + initial: "", isTransient: true, customGetter: Person.getName(_:) ) @@ -289,7 +290,7 @@ public enum ValueContainer { The containing type for optional value properties. Any type that conforms to `ImportableAttributeType` are supported. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let color = Transformable.Optional("color") } diff --git a/Sources/VersionLock.swift b/Sources/VersionLock.swift index 38fff5c..4316004 100644 --- a/Sources/VersionLock.swift +++ b/Sources/VersionLock.swift @@ -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. ``` class Animal: CoreStoreObject { - let species = Value.Required("species") + let species = Value.Required("species", initial: "") let nickname = Value.Optional("nickname") let master = Relationship.ToOne("master") } class Person: CoreStoreObject { - let name = Value.Required("name") + let name = Value.Required("name", initial: "") let pet = Relationship.ToOne("pet", inverse: { $0.master }) } From d2ddf2002f62a4919df8981f312b47b70c20ae81 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Wed, 11 Oct 2017 22:40:27 +0900 Subject: [PATCH 13/17] version update --- .travis.yml | 35 +++++++++++++++++++---------------- CoreStore.podspec | 2 +- Sources/Info.plist | 2 +- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5a30d91..aaa35e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8.3 +osx_image: xcode9 sudo: false git: submodules: false @@ -10,22 +10,25 @@ env: - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 matrix: - - DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.3 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO" - - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.2 RUN_TESTS="NO" POD_LINT="NO" - - DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO" - - DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=11.0,name=iPhone 8" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=10.3,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.13 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=4.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO" + - DESTINATION="OS=3.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO" + - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator4.0 RUN_TESTS="NO" POD_LINT="NO" + - DESTINATION="OS=11.0,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=10.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator11.0 RUN_TESTS="YES" POD_LINT="NO" before_install: - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet - - curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.23.0/Carthage.pkg" + - curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.26.0/Carthage.pkg" - sudo installer -pkg "Carthage.pkg" -target / - rm "Carthage.pkg" before_script: @@ -38,8 +41,8 @@ script: xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; fi - - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.3" -destination "OS=10.3,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - if [ $POD_LINT == "YES" ]; then pod lib lint --quick; fi diff --git a/CoreStore.podspec b/CoreStore.podspec index fef69a2..5c3660e 100644 --- a/CoreStore.podspec +++ b/CoreStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CoreStore" - s.version = "4.1.3" + s.version = "4.2.0" s.license = "MIT" s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift" s.homepage = "https://github.com/JohnEstropia/CoreStore" diff --git a/Sources/Info.plist b/Sources/Info.plist index a19ea3e..b6ba904 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 4.1.3 + 4.2.0 CFBundleSignature ???? CFBundleVersion From 50bc3ace069e18f98ad460521fad4b5e085c59ab Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Thu, 12 Oct 2017 00:02:39 +0900 Subject: [PATCH 14/17] travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index aaa35e4..af7dac8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,8 @@ before_install: - curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.26.0/Carthage.pkg" - sudo installer -pkg "Carthage.pkg" -target / - rm "Carthage.pkg" + - npm install ios-sim -g + - ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 11.0" before_script: - carthage update --use-submodules script: From f460a0b30f4e2cb6863863c53ac157a000439b85 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Thu, 12 Oct 2017 01:10:08 +0900 Subject: [PATCH 15/17] CI: test demo app --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index af7dac8..174671a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,8 +43,8 @@ script: xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; fi - - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c; + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStoreDemo" -sdk "iphonesimulator11.0" -destination "OS=11.0,name=iPhone 8" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c; - if [ $POD_LINT == "YES" ]; then pod lib lint --quick; fi From ab2eac8f6ccbadd56ee6db9c683b4129511f4acf Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Fri, 13 Oct 2017 07:58:37 +0900 Subject: [PATCH 16/17] Swift 3.2 README update --- README.md | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 38c4ab5..8c91861 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ Unleashing the real power of Core Data with the elegance and safety of Swift

-* **Swift 3.1:** iOS 8+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+ -* Beta support: [Swift 3.2](https://github.com/JohnEstropia/CoreStore/tree/prototype/Swift_3_2), [Swift 4.0](https://github.com/JohnEstropia/CoreStore/tree/prototype/Swift_4_0) +* **Swift 3.2:** iOS 8+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+ +* Other Swift versions: [Swift 3.1(version 4.1.4)](https://github.com/JohnEstropia/CoreStore/tree/4.1.4), [Swift 4.0](https://github.com/JohnEstropia/CoreStore/tree/5.0.0) -Upgrading from CoreStore 3.x to 4.x? Check out the [new features](#features) and make sure to read the [Migration guide](#upgrading-from-3xx-to-4xx). +Upgrading from CoreStore 4.1 (Swift 3.1) to 4.2 (Swift 3.2)? Check out the [new features](#features) and make sure to read the [Change logs](https://github.com/JohnEstropia/CoreStore/releases). CoreStore is now part of the [Swift Source Compatibility projects](https://swift.org/source-compatibility/#current-list-of-projects). @@ -38,9 +38,9 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep - **Clean fetching and querying API.** Fetching objects is easy, but querying for raw aggregates (`min`, `max`, etc.) and raw property values is now just as convenient. *(See [Fetching and querying](#fetching-and-querying))* - **Type-safe, easy to configure observers.** You don't have to deal with the burden of setting up `NSFetchedResultsController`s and KVO. As an added bonus, `ListMonitor`s and `ObjectMonitor`s can have multiple observers. This means you can have multiple view controllers efficiently share a single resource! *(See [Observing changes and notifications](#observing-changes-and-notifications))* - **Efficient importing utilities.** Map your entities once with their corresponding import source (JSON for example), and importing from *transactions* becomes elegant. Uniquing is also done with an efficient find-and-replace algorithm. *(See [Importing data](#importing-data))* -- ⭐️ **New in 4.0: Say goodbye to *.xcdatamodeld* files!** The new `CoreStoreObject` is *the* replacement to `NSManagedObject`. `CoreStoreObject` subclasses can declare type-safe properties all in Swift code, no need to maintain separate resource files for the models. As bonus, these special properties support custom types, and can be used to create type-safe keypaths and queries. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))* +- **Say goodbye to *.xcdatamodeld* files!** The new `CoreStoreObject` is *the* replacement to `NSManagedObject`. `CoreStoreObject` subclasses can declare type-safe properties all in Swift code, no need to maintain separate resource files for the models. As bonus, these special properties support custom types, and can be used to create type-safe keypaths and queries. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))* - **Progressive migrations.** No need to think how to migrate from all previous model versions to your latest model. Just tell the `DataStack` the sequence of version strings (`MigrationChain`s) and CoreStore will automatically use progressive migrations when needed. *(See [Migrations](#migrations))* -- ⭐️ **New in 4.0: Easier custom migrations.** Say goodbye to *.xcmappingmodel* files; CoreStore can now infer entity mappings when possible, while still allowing an easy way to write custom mappings. *(See [Migrations](#migrations))* +- **Easier custom migrations.** Say goodbye to *.xcmappingmodel* files; CoreStore can now infer entity mappings when possible, while still allowing an easy way to write custom mappings. *(See [Migrations](#migrations))* - **Plug-in your own logging framework.** Although a default logger is built-in, all logging, asserting, and error reporting can be funneled to `CoreStoreLogger` protocol implementations. *(See [Logging and error reporting](#logging-and-error-reporting))* - **Heavy support for multiple persistent stores per data stack.** CoreStore lets you manage separate stores in a single `DataStack`, just the way *.xcdatamodeld* configurations are designed to. CoreStore will also manage one stack by default, but you can create and manage as many as you need. *(See [Setting up](#setting-up))* - **Free to name entities and their class names independently.** CoreStore gets around a restriction with other Core Data wrappers where the entity name should be the same as the `NSManagedObject` subclass name. CoreStore loads entity-to-class mappings from the managed object model file, so you can assign different names for the entities and their class names. @@ -95,8 +95,6 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep - [Roadmap](#roadmap) - [Installation](#installation) - [Changesets](#changesets) - - [Upgrading from 3.x.x to 4.x.x](#upgrading-from-3xx-to-4xx) - - [Other Releases](#other-releases) - [Contact](#contact) - [Who uses CoreStore?](#who-uses-corestore) - [License](#license) @@ -1832,22 +1830,6 @@ Add all *.swift* files to your project. To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files. # Changesets -### Upgrading from 3.x.x to 4.x.x -**Obsoleted** -- `LegacySQLiteStore` is now finally obsoleted in favor of `SQLiteStore`. For sqlite files that were created previously with `LegacySQLiteStore`, make sure to use the `SQLiteStore.legacy(...)` factory method to create an `SQLiteStore` that can load the file from the legacy file path. -- `SQLiteStore.init(...)`'s `mappingModelBundles` argument is now obsolete. The new initializer accepts a `migrationMappingProviders` optional argument where explicit mapping sources are declared. For reference on how to do this, read on [Custom migrations](#custom-migrations). - -**Deprecated** -- `DataStack.beginAsynchronous(...)`, `DataStack.beginSynchronous(...)`, `AsynchronousDataTransaction.commit(...)`, and `SynchronousDataTransaction.commit(...)` are now deprecated in favor of `DataStack.perform(asynchronous:...)` and `DataStack.perform(synchronous:...)` family of methods. These new `perform(...)` methods are auto-commit, meaning the transaction automatically calls `commit()` internally after the transction closure completes. To roll-back and cancel a transaction, call `try transaction.cancel()`. Read [Saving and processing transactions](#saving-and-processing-transactions) for more details. - -**Other Changes** -- `ListMonitor.refetch(...)` now works by recreating its internal `NSFetchedResultsController`. Previously `refetch(...)` would only apply new `FetchClause`s on top of previous fetches. Now all `FetchClauses` are required to be passed to `refetch(...)` each time it is called. -- New important concepts on "Dynamic Models", "Schema", and "Schema Histories". - - **Dynamic Models** (`DynamicObject` protocol): These are Core Data object types that any `NSManagedObject` or `CoreStoreObject`s conform to. *(See [Type-safe `CoreStoreObject`s](#type-safe-corestoreobjects))* - - **Version Schema** (`DynamicSchema` protocol): These types contain info for a single model version, as well as entities that belong to it. Currently supports `XcodeDataModelSchema` (*.xcdatamodeld* file), `CoreStoreSchema`, or `UnsafeDataModelSchema`. *(See [Migrations](#migrations))* - - **Schema History** (`SchemaHistory` class): This is now the preferred way to express all models to the `DataStack`. This class contains info to all the `DynamicSchema` across multiple model versions. *(See [Migrations](#migrations))* - -### Other Releases For the full Changelog, refer to the [Releases](https://github.com/JohnEstropia/CoreStore/releases) page. From ba6f0c39d5d3a3401396f0bbba9c10a6d2978b50 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Fri, 13 Oct 2017 08:00:39 +0900 Subject: [PATCH 17/17] swift version 3.2 --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index 8c50098..a3ec5a4 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -3.1 +3.2