From 5b85b0749e410362f1c951ec2a4809bd30417859 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Tue, 7 Jul 2015 08:03:46 +0900 Subject: [PATCH] migration utilities (beta), swift 2 conversion --- CoreStore.xcodeproj/project.pbxproj | 12 +- .../xcshareddata/CoreStore.xcscmblueprint | 30 +++ .../xcshareddata/xcschemes/CoreStore.xcscheme | 5 +- .../BaseDataTransaction+Querying.swift | 184 +++++++++++------- .../Concrete Clauses/GroupBy.swift | 11 +- .../Concrete Clauses/OrderBy.swift | 19 +- .../Concrete Clauses/Select.swift | 61 +++--- .../Concrete Clauses/Tweak.swift | 2 +- .../Concrete Clauses/Where.swift | 21 +- .../CoreStore+Querying.swift | 92 ++++----- CoreStore/Info.plist | 2 +- CoreStore/Internal/AssociatedObjects.swift | 10 +- .../NSManagedObject+Transaction.swift | 56 ++++-- .../NSManagedObjectContext+CoreStore.swift | 21 +- .../NSManagedObjectContext+Querying.swift | 115 ++++++++--- .../NSManagedObjectContext+Transaction.swift | 101 +++++----- .../Internal/NSManagedObjectModel+Setup.swift | 183 ++++++++++++++--- CoreStore/Internal/NotificationObserver.swift | 2 +- .../Internal/RootManagedObjectModel.swift | 13 -- CoreStore/Logging/CoreStore+Logging.swift | 16 +- CoreStore/Logging/CoreStoreLogger.swift | 20 +- CoreStore/Logging/DefaultLogger.swift | 17 +- CoreStore/Migrating/MigrationChain.swift | 11 +- CoreStore/Observing/CoreStore+Observing.swift | 32 +-- CoreStore/Observing/ListMonitor.swift | 90 +++++---- CoreStore/Observing/ListObserver.swift | 42 ++-- CoreStore/Observing/ObjectMonitor.swift | 53 +++-- CoreStore/Observing/ObjectObserver.swift | 14 +- CoreStore/Observing/SectionBy.swift | 6 +- .../AsynchronousDataTransaction.swift | 106 +++++++--- .../BaseDataTransaction.swift | 80 +++++--- .../CoreStore+Transaction.swift | 8 +- .../DetachedDataTransaction.swift | 7 +- CoreStore/Saving and Processing/Into.swift | 14 +- .../Saving and Processing/SaveResult.swift | 4 +- .../SynchronousDataTransaction.swift | 89 ++++++--- CoreStore/Setting Up/CoreStore+Setup.swift | 24 +-- .../CoreStoreDemo.xcodeproj/project.pbxproj | 28 ++- .../xcshareddata/CoreStoreDemo.xccheckout | 4 +- .../xcshareddata/CoreStoreDemo.xcscmblueprint | 30 +++ .../xcschemes/CoreStoreDemo.xcscheme | 5 +- .../CoreStoreDemo/Base.lproj/Main.storyboard | 117 +++++++++-- ...etchingAndQueryingDemoViewController.swift | 4 +- .../FetchingResultsViewController.swift | 2 +- .../QueryingResultsViewController.swift | 2 +- CoreStoreDemo/CoreStoreDemo/Info.plist | 2 +- .../ObjectObserverDemoViewController.swift | 4 - .../CustomLoggerViewController.swift | 11 +- .../MigrationsDemoViewController.swift | 149 +++++++------- .../xcmapping.xml | 54 ++--- .../OrganismV2ToV3MigrationPolicy.swift | 8 +- .../MigrationDemoV2.xcdatamodel/contents | 2 +- .../MigrationDemoV3.xcdatamodel/contents | 2 +- .../StackSetupDemoViewController.swift | 2 +- .../TransactionsDemoViewController.swift | 6 +- CoreStoreTests/CoreStoreTests.swift | 27 ++- CoreStoreTests/Info.plist | 2 +- Libraries/GCDKit | 2 +- README.md | 16 +- 59 files changed, 1319 insertions(+), 733 deletions(-) create mode 100644 CoreStore.xcodeproj/project.xcworkspace/xcshareddata/CoreStore.xcscmblueprint delete mode 100644 CoreStore/Internal/RootManagedObjectModel.swift create mode 100644 CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xcscmblueprint diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 5053325..484d19a 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; }; 2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; }; B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; }; + B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; }; B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; }; B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007131B3F6C2800A9A8F9 /* SectionBy.swift */; }; B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007151B4018AB00A9A8F9 /* MigrationChain.swift */; }; @@ -104,6 +105,7 @@ 2F03A54C19C5C872005002A5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 2F291E2619C6D3CF007AF63F /* CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStore.swift; sourceTree = ""; }; B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = ""; }; + B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = ""; }; B56007101B3F6BD500A9A8F9 /* Into.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Into.swift; sourceTree = ""; }; B56007131B3F6C2800A9A8F9 /* SectionBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionBy.swift; sourceTree = ""; }; B56007151B4018AB00A9A8F9 /* MigrationChain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChain.swift; sourceTree = ""; }; @@ -389,6 +391,7 @@ isa = PBXGroup; children = ( B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */, + B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */, B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */, B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */, B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */, @@ -457,7 +460,8 @@ 2F03A52719C5C6DA005002A5 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "John Rommel Estropia"; TargetAttributes = { 2F03A52F19C5C6DA005002A5 = { @@ -564,6 +568,7 @@ B5E84F0F1AFF847B0064E85B /* From.swift in Sources */, B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */, B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */, + B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */, B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */, B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */, B5E84F311AFF849C0064E85B /* WeakObject.swift in Sources */, @@ -628,6 +633,7 @@ COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -707,6 +713,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; OTHER_SWIFT_FLAGS = "-D DEBUG"; + PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -727,6 +734,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -748,6 +756,7 @@ ); INFOPLIST_FILE = CoreStoreTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -762,6 +771,7 @@ ); INFOPLIST_FILE = CoreStoreTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/CoreStore.xcodeproj/project.xcworkspace/xcshareddata/CoreStore.xcscmblueprint b/CoreStore.xcodeproj/project.xcworkspace/xcshareddata/CoreStore.xcscmblueprint new file mode 100644 index 0000000..4cf66a2 --- /dev/null +++ b/CoreStore.xcodeproj/project.xcworkspace/xcshareddata/CoreStore.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "4B60F1BCB491FF717C56441AE7783C74F417BE48", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "8B2E522D57154DFA93A06982C36315ECBEA4FA97" : 0, + "4B60F1BCB491FF717C56441AE7783C74F417BE48" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "F347F55F-7F5C-4476-9148-6E902F06E4AD", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "8B2E522D57154DFA93A06982C36315ECBEA4FA97" : "CoreStoreLibraries\/GCDKit", + "4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "CoreStore", + "DVTSourceControlWorkspaceBlueprintVersion" : 203, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CoreStore.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:JohnEstropia\/CoreStore.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "4B60F1BCB491FF717C56441AE7783C74F417BE48" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:JohnEstropia\/GCDKit.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8B2E522D57154DFA93A06982C36315ECBEA4FA97" + } + ] +} \ No newline at end of file diff --git a/CoreStore.xcodeproj/xcshareddata/xcschemes/CoreStore.xcscheme b/CoreStore.xcodeproj/xcshareddata/xcschemes/CoreStore.xcscheme index 24b8263..3cf883e 100644 --- a/CoreStore.xcodeproj/xcshareddata/xcschemes/CoreStore.xcscheme +++ b/CoreStore.xcodeproj/xcshareddata/xcschemes/CoreStore.xcscheme @@ -1,6 +1,6 @@ + + (from: From, _ fetchClauses: FetchClause...) -> T? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchOne(from, fetchClauses) } @@ -50,13 +53,16 @@ public extension BaseDataTransaction { /** Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s */ public func fetchOne(from: From, _ fetchClauses: [FetchClause]) -> T? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchOne(from, fetchClauses) } @@ -64,13 +70,16 @@ public extension BaseDataTransaction { /** Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s */ public func fetchAll(from: From, _ fetchClauses: FetchClause...) -> [T]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchAll(from, fetchClauses) } @@ -78,13 +87,16 @@ public extension BaseDataTransaction { /** Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s */ public func fetchAll(from: From, _ fetchClauses: [FetchClause]) -> [T]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchAll(from, fetchClauses) } @@ -92,13 +104,16 @@ public extension BaseDataTransaction { /** Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s */ public func fetchCount(from: From, _ fetchClauses: FetchClause...) -> Int? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchCount(from, fetchClauses) } @@ -106,13 +121,16 @@ public extension BaseDataTransaction { /** Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s */ public func fetchCount(from: From, _ fetchClauses: [FetchClause]) -> Int? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchCount(from, fetchClauses) } @@ -120,13 +138,16 @@ public extension BaseDataTransaction { /** Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s */ public func fetchObjectID(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchObjectID(from, fetchClauses) } @@ -134,13 +155,16 @@ public extension BaseDataTransaction { /** Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s */ public func fetchObjectID(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchObjectID(from, fetchClauses) } @@ -148,13 +172,16 @@ public extension BaseDataTransaction { /** Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s */ public func fetchObjectIDs(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchObjectIDs(from, fetchClauses) } @@ -162,13 +189,16 @@ public extension BaseDataTransaction { /** Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s */ public func fetchObjectIDs(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to fetch from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to fetch from a \(typeName(self)) outside its designated queue." + ) return self.context.fetchObjectIDs(from, fetchClauses) } @@ -176,13 +206,16 @@ public extension BaseDataTransaction { /** Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: deleteClauses a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number of `NSManagedObject`s deleted + - parameter from: a `From` clause indicating the entity type + - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number of `NSManagedObject`s deleted */ public func deleteAll(from: From, _ deleteClauses: DeleteClause...) -> Int? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to delete from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to delete from a \(typeName(self)) outside its designated queue." + ) return self.context.deleteAll(from, deleteClauses) } @@ -190,13 +223,16 @@ public extension BaseDataTransaction { /** Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: deleteClauses a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number of `NSManagedObject`s deleted + - parameter from: a `From` clause indicating the entity type + - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number of `NSManagedObject`s deleted */ public func deleteAll(from: From, _ deleteClauses: [DeleteClause]) -> Int? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to delete from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to delete from a \(typeName(self)) outside its designated queue." + ) return self.context.deleteAll(from, deleteClauses) } @@ -206,14 +242,17 @@ public extension BaseDataTransaction { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to query from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to query from a \(typeName(self)) outside its designated queue." + ) return self.context.queryValue(from, selectClause, queryClauses) } @@ -223,14 +262,17 @@ public extension BaseDataTransaction { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to query from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to query from a \(typeName(self)) outside its designated queue." + ) return self.context.queryValue(from, selectClause, queryClauses) } @@ -240,14 +282,17 @@ public extension BaseDataTransaction { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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...) -> [[NSString: AnyObject]]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to query from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to query from a \(typeName(self)) outside its designated queue." + ) return self.context.queryAttributes(from, selectClause, queryClauses) } @@ -257,14 +302,17 @@ public extension BaseDataTransaction { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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]) -> [[NSString: AnyObject]]? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to query from a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to query from a \(typeName(self)) outside its designated queue." + ) return self.context.queryAttributes(from, selectClause, queryClauses) } diff --git a/CoreStore/Fetching and Querying/Concrete Clauses/GroupBy.swift b/CoreStore/Fetching and Querying/Concrete Clauses/GroupBy.swift index b01c1ae..53d3b1a 100644 --- a/CoreStore/Fetching and Querying/Concrete Clauses/GroupBy.swift +++ b/CoreStore/Fetching and Querying/Concrete Clauses/GroupBy.swift @@ -39,7 +39,7 @@ public struct GroupBy: QueryClause { /** Initializes a `GroupBy` clause with a list of key path strings - :param: keyPaths a list of key path strings to group results with + - parameter keyPaths: a list of key path strings to group results with */ public init(_ keyPaths: [KeyPath]) { @@ -57,8 +57,8 @@ public struct GroupBy: QueryClause { /** Initializes a `GroupBy` clause with a list of key path strings - :param: keyPath a key path string to group results with - :param: keyPaths a series of key path strings to group results with + - 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...) { @@ -74,7 +74,10 @@ public struct GroupBy: QueryClause { if fetchRequest.propertiesToGroupBy != nil { - CoreStore.log(.Warning, message: "An existing \"propertiesToGroupBy\" for the <\(NSFetchRequest.self)> was overwritten by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "An existing \"propertiesToGroupBy\" for the \(typeName(NSFetchRequest)) was overwritten by \(typeName(self)) query clause." + ) } fetchRequest.propertiesToGroupBy = self.keyPaths diff --git a/CoreStore/Fetching and Querying/Concrete Clauses/OrderBy.swift b/CoreStore/Fetching and Querying/Concrete Clauses/OrderBy.swift index c1b3416..1cffc29 100644 --- a/CoreStore/Fetching and Querying/Concrete Clauses/OrderBy.swift +++ b/CoreStore/Fetching and Querying/Concrete Clauses/OrderBy.swift @@ -73,7 +73,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause { /** Initializes a `OrderBy` clause with a list of sort descriptors - :param: sortDescriptors a series of `NSSortDescriptor`s + - parameter sortDescriptors: a series of `NSSortDescriptor`s */ public init(_ sortDescriptors: [NSSortDescriptor]) { @@ -91,7 +91,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause { /** Initializes a `OrderBy` clause with a single sort descriptor - :param: sortDescriptor a `NSSortDescriptor` + - parameter sortDescriptor: a `NSSortDescriptor` */ public init(_ sortDescriptor: NSSortDescriptor) { @@ -101,14 +101,14 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause { /** Initializes a `OrderBy` clause with a series of `SortKey`s - :param: sortKey a series of `SortKey`s + - parameter sortKey: a series of `SortKey`s */ public init(_ sortKey: [SortKey]) { self.init( - sortKey.map { SortKey -> NSSortDescriptor in + sortKey.map { sortKey -> NSSortDescriptor in - switch SortKey { + switch sortKey { case .Ascending(let keyPath): return NSSortDescriptor(key: keyPath, ascending: true) @@ -123,8 +123,8 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause { /** Initializes a `OrderBy` clause with a series of `SortKey`s - :param: sortKey a single `SortKey` - :param: sortKeys a series of `SortKey`s + - parameter sortKey: a single `SortKey` + - parameter sortKeys: a series of `SortKey`s */ public init(_ sortKey: SortKey, _ sortKeys: SortKey...) { @@ -140,7 +140,10 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause { if fetchRequest.sortDescriptors != nil { - CoreStore.log(.Warning, message: "Existing sortDescriptors for the <\(NSFetchRequest.self)> was overwritten by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "Existing sortDescriptors for the \(typeName(NSFetchRequest)) was overwritten by \(typeName(self)) query clause." + ) } fetchRequest.sortDescriptors = self.sortDescriptors diff --git a/CoreStore/Fetching and Querying/Concrete Clauses/Select.swift b/CoreStore/Fetching and Querying/Concrete Clauses/Select.swift index 0b179f5..3653164 100644 --- a/CoreStore/Fetching and Querying/Concrete Clauses/Select.swift +++ b/CoreStore/Fetching and Querying/Concrete Clauses/Select.swift @@ -83,8 +83,8 @@ public enum SelectTerm: StringLiteralConvertible { Where("employeeID", isEqualTo: 1111) ) - :param: keyPath the attribute name - :returns: a `SelectTerm` to a `Select` clause for querying an entity attribute + - parameter keyPath: the attribute name + - returns: a `SelectTerm` to a `Select` clause for querying an entity attribute */ public static func Attribute(keyPath: KeyPath) -> SelectTerm { @@ -99,9 +99,9 @@ public enum SelectTerm: StringLiteralConvertible { Select(.Average("age")) ) - :param: keyPath the attribute name - :param: 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 + - parameter keyPath: the attribute name + - 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 { @@ -121,9 +121,9 @@ public enum SelectTerm: StringLiteralConvertible { Select(.Count("employeeID")) ) - :param: keyPath the attribute name - :param: 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 + - parameter keyPath: the attribute name + - 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 { @@ -143,9 +143,9 @@ public enum SelectTerm: StringLiteralConvertible { Select(.Maximum("age")) ) - :param: keyPath the attribute name - :param: 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 + - parameter keyPath: the attribute name + - 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 { @@ -165,9 +165,9 @@ public enum SelectTerm: StringLiteralConvertible { Select(.Minimum("age")) ) - :param: keyPath the attribute name - :param: 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 + - parameter keyPath: the attribute name + - 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 { @@ -187,9 +187,9 @@ public enum SelectTerm: StringLiteralConvertible { Select(.Sum("age")) ) - :param: keyPath the attribute name - :param: 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 + - parameter keyPath: the attribute name + - 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 { @@ -267,7 +267,7 @@ Valid return types depend on the query: - for `queryAttributes(...)` methods: - `NSDictionary` -:param: sortDescriptors a series of `NSSortDescriptor`s +- parameter sortDescriptors: a series of `NSSortDescriptor`s */ public struct Select { @@ -281,8 +281,8 @@ public struct Select { /** Initializes a `Select` clause with a list of `SelectTerm`s - :param: selectTerm a `SelectTerm` - :param: selectTerms a series of `SelectTerm`s + - parameter selectTerm: a `SelectTerm` + - parameter selectTerms: a series of `SelectTerm`s */ public init(_ selectTerm: SelectTerm, _ selectTerms: SelectTerm...) { @@ -296,7 +296,10 @@ public struct Select { if fetchRequest.propertiesToFetch != nil { - CoreStore.log(.Warning, message: "An existing \"propertiesToFetch\" for the <\(NSFetchRequest.self)> was overwritten by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "An existing \"propertiesToFetch\" for the \(typeName(NSFetchRequest)) was overwritten by \(typeName(self)) query clause." + ) } fetchRequest.includesPendingChanges = false @@ -312,17 +315,20 @@ public struct Select { switch term { case ._Attribute(let keyPath): - if let propertyDescription = propertiesByName[keyPath] as? NSPropertyDescription { + if let propertyDescription = propertiesByName[keyPath] { propertiesToFetch.append(propertyDescription) } else { - CoreStore.log(.Warning, message: "The property \"\(keyPath)\" does not exist in entity <\(entityDescription.managedObjectClassName)> and will be ignored by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "The property \"\(keyPath)\" does not exist in entity \(typeName(entityDescription.managedObjectClassName)) and will be ignored by \(typeName(self)) query clause." + ) } case ._Aggregate(let function, let keyPath, let alias, let nativeType): - if let attributeDescription = attributesByName[keyPath] as? NSAttributeDescription { + if let attributeDescription = attributesByName[keyPath] { let expressionDescription = NSExpressionDescription() expressionDescription.name = alias @@ -343,7 +349,10 @@ public struct Select { } else { - CoreStore.log(.Warning, message: "The attribute \"\(keyPath)\" does not exist in entity <\(entityDescription.managedObjectClassName)> and will be ignored by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "The attribute \"\(keyPath)\" does not exist in entity \(typeName(entityDescription.managedObjectClassName)) and will be ignored by \(typeName(self)) query clause." + ) } } } @@ -572,7 +581,7 @@ extension NSString: SelectValueResultType { // MARK: - NSDecimalNumber: SelectValueResultType -extension NSDecimalNumber: SelectValueResultType { +extension NSDecimalNumber { public override class var attributeType: NSAttributeType { diff --git a/CoreStore/Fetching and Querying/Concrete Clauses/Tweak.swift b/CoreStore/Fetching and Querying/Concrete Clauses/Tweak.swift index 080d74b..299d154 100644 --- a/CoreStore/Fetching and Querying/Concrete Clauses/Tweak.swift +++ b/CoreStore/Fetching and Querying/Concrete Clauses/Tweak.swift @@ -49,7 +49,7 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause { /** Initializes a `Tweak` clause with a closure where the `NSFetchRequest` may be configured. - :param: customization a list of key path strings to group results with + - parameter customization: a list of key path strings to group results with */ public init(_ customization: (fetchRequest: NSFetchRequest) -> Void) { diff --git a/CoreStore/Fetching and Querying/Concrete Clauses/Where.swift b/CoreStore/Fetching and Querying/Concrete Clauses/Where.swift index 1f80d57..1762b31 100644 --- a/CoreStore/Fetching and Querying/Concrete Clauses/Where.swift +++ b/CoreStore/Fetching and Querying/Concrete Clauses/Where.swift @@ -54,7 +54,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause { /** Initializes a `Where` clause with an `NSPredicate` - :param: predicate the `NSPredicate` for the fetch or query + - parameter predicate: the `NSPredicate` for the fetch or query */ public init(_ predicate: NSPredicate) { @@ -72,7 +72,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause { /** Initializes a `Where` clause with a predicate that always evaluates to the specified boolean value - :param: value the boolean value for the predicate + - parameter value: the boolean value for the predicate */ public init(_ value: Bool) { @@ -82,8 +82,8 @@ public struct Where: FetchClause, QueryClause, DeleteClause { /** Initializes a `Where` clause with a predicate using the specified string format and arguments - :param: format the format string for the predicate - :param: args the arguments for `format` + - parameter format: the format string for the predicate + - parameter args: the arguments for `format` */ public init(_ format: String, _ args: NSObject...) { @@ -93,8 +93,8 @@ public struct Where: FetchClause, QueryClause, DeleteClause { /** Initializes a `Where` clause with a predicate using the specified string format and arguments - :param: format the format string for the predicate - :param: argumentArray the arguments for `format` + - parameter format: the format string for the predicate + - parameter argumentArray: the arguments for `format` */ public init(_ format: String, argumentArray: [NSObject]?) { @@ -104,8 +104,8 @@ public struct Where: FetchClause, QueryClause, DeleteClause { /** Initializes a `Where` clause with a predicate using the specified string format and arguments - :param: format the format string for the predicate - :param: argumentArray the arguments for `format` + - parameter format: the format string for the predicate + - parameter argumentArray: the arguments for `format` */ public init(_ keyPath: KeyPath, isEqualTo value: NSObject?) { @@ -123,7 +123,10 @@ public struct Where: FetchClause, QueryClause, DeleteClause { if fetchRequest.predicate != nil { - CoreStore.log(.Warning, message: "An existing predicate for the <\(NSFetchRequest.self)> was overwritten by \(typeName(self)) query clause.") + CoreStore.log( + .Warning, + message: "An existing predicate for the \(typeName(NSFetchRequest)) was overwritten by \(typeName(self)) query clause." + ) } fetchRequest.predicate = self.predicate diff --git a/CoreStore/Fetching and Querying/CoreStore+Querying.swift b/CoreStore/Fetching and Querying/CoreStore+Querying.swift index efa7d4a..1d28e95 100644 --- a/CoreStore/Fetching and Querying/CoreStore+Querying.swift +++ b/CoreStore/Fetching and Querying/CoreStore+Querying.swift @@ -34,9 +34,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s */ public static func fetchOne(from: From, _ fetchClauses: FetchClause...) -> T? { @@ -46,9 +46,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s */ public static func fetchOne(from: From, _ fetchClauses: [FetchClause]) -> T? { @@ -58,9 +58,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s */ public static func fetchAll(from: From, _ fetchClauses: FetchClause...) -> [T]? { @@ -70,9 +70,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s */ public static func fetchAll(from: From, _ fetchClauses: [FetchClause]) -> [T]? { @@ -82,9 +82,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s */ public static func fetchCount(from: From, _ fetchClauses: FetchClause...) -> Int? { @@ -94,9 +94,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s */ public static func fetchCount(from: From, _ fetchClauses: [FetchClause]) -> Int? { @@ -106,9 +106,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s */ public static func fetchObjectID(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { @@ -118,9 +118,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s */ public static func fetchObjectID(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { @@ -130,9 +130,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s */ public static func fetchObjectIDs(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { @@ -142,9 +142,9 @@ public extension CoreStore { /** Using the `defaultStack`, fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :param: from a `From` clause indicating the entity type - :param: fetchClauses a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - :returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s + - parameter from: a `From` clause indicating the entity type + - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses. + - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s */ public static func fetchObjectIDs(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { @@ -156,10 +156,10 @@ public extension CoreStore { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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? { @@ -171,10 +171,10 @@ public extension CoreStore { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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? { @@ -186,10 +186,10 @@ public extension CoreStore { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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...) -> [[NSString: AnyObject]]? { @@ -201,10 +201,10 @@ public extension CoreStore { A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. - :param: from a `From` clause indicating the entity type - :param: selectClause a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. - :param: 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. + - parameter from: a `From` clause indicating the entity type + - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type. + - 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]) -> [[NSString: AnyObject]]? { diff --git a/CoreStore/Info.plist b/CoreStore/Info.plist index 5b188f2..60b9c00 100644 --- a/CoreStore/Info.plist +++ b/CoreStore/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.johnestropia.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/CoreStore/Internal/AssociatedObjects.swift b/CoreStore/Internal/AssociatedObjects.swift index 34cb330..2018a37 100644 --- a/CoreStore/Internal/AssociatedObjects.swift +++ b/CoreStore/Internal/AssociatedObjects.swift @@ -42,27 +42,27 @@ internal func getAssociatedObjectForKey(key: UnsafePointer, internal func setAssociatedRetainedObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) { - objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) + objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } internal func setAssociatedCopiedObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) { - objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_COPY_NONATOMIC)) + objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_COPY_NONATOMIC) } internal func setAssociatedAssignedObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) { - objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_ASSIGN)) + objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_ASSIGN) } internal func setAssociatedWeakObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) { if let associatedObject = associatedObject { - objc_setAssociatedObject(object, key, WeakObject(associatedObject), UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) + objc_setAssociatedObject(object, key, WeakObject(associatedObject), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } else { - objc_setAssociatedObject(object, key, nil, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) + objc_setAssociatedObject(object, key, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } diff --git a/CoreStore/Internal/NSManagedObject+Transaction.swift b/CoreStore/Internal/NSManagedObject+Transaction.swift index 233c2e8..9ef9ac4 100644 --- a/CoreStore/Internal/NSManagedObject+Transaction.swift +++ b/CoreStore/Internal/NSManagedObject+Transaction.swift @@ -35,7 +35,7 @@ internal extension NSManagedObject { internal dynamic class func createInContext(context: NSManagedObjectContext) -> Self { - return self( + return self.init( entity: context.entityDescriptionForEntityType(self)!, insertIntoManagedObjectContext: context ) @@ -61,16 +61,19 @@ internal extension NSManagedObject { private class func typedObjectInContext(context: NSManagedObjectContext, objectID: NSManagedObjectID) -> T? { - var error: NSError? - if let existingObject = context.existingObjectWithID(objectID, error: &error) { + do { + let existingObject = try context.existingObjectWithID(objectID) return (existingObject as! T) } - - CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to load existing \(typeName(self)) in context.") - return nil; + catch { + + CoreStore.handleError( + error as NSError, + "Failed to load existing \(typeName(self)) in context." + ) + return nil + } } private func typedObjectInContext(context: NSManagedObjectContext) -> T? { @@ -78,29 +81,42 @@ internal extension NSManagedObject { let objectID = self.objectID if objectID.temporaryID { - var error: NSError? - let didSucceed = withExtendedLifetime(self.managedObjectContext) { + var objectIDError: NSError? + let didSucceed = withExtendedLifetime(self.managedObjectContext) { (context: NSManagedObjectContext?) -> Bool in - return $0?.obtainPermanentIDsForObjects([self], error: &error) + do { + + try context?.obtainPermanentIDsForObjects([self]) + return true + } + catch { + + objectIDError = error as NSError + return false + } } if didSucceed != true { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to obtain permanent ID for object.") + objectIDError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed to obtain permanent ID for object." + ) return nil } } - var error: NSError? - if let existingObject = context.existingObjectWithID(objectID, error: &error) { + do { + let existingObject = try context.existingObjectWithID(objectID) return (existingObject as! T) } - - CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to load existing \(typeName(self)) in context.") - return nil; + catch { + + CoreStore.handleError( + error as NSError, + "Failed to load existing \(typeName(self)) in context." + ) + return nil + } } } diff --git a/CoreStore/Internal/NSManagedObjectContext+CoreStore.swift b/CoreStore/Internal/NSManagedObjectContext+CoreStore.swift index f4e2f1e..cf69c65 100644 --- a/CoreStore/Internal/NSManagedObjectContext+CoreStore.swift +++ b/CoreStore/Internal/NSManagedObjectContext+CoreStore.swift @@ -73,10 +73,7 @@ internal extension NSManagedObjectContext { internal func setupForCoreStoreWithContextName(contextName: String) { - if self.respondsToSelector("setName:") { - - self.name = contextName - } + self.name = contextName self.observerForWillSaveNotification = NotificationObserver( notificationName: NSManagedObjectContextWillSaveNotification, @@ -91,16 +88,18 @@ internal extension NSManagedObjectContext { return } - var error: NSError? - if context.obtainPermanentIDsForObjects(Array(insertedObjects), error: &error) { + do { + try context.obtainPermanentIDsForObjects(Array(insertedObjects)) return } - - CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s)." - ) + catch { + + CoreStore.handleError( + error as NSError, + "Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s)." + ) + } } ) } diff --git a/CoreStore/Internal/NSManagedObjectContext+Querying.swift b/CoreStore/Internal/NSManagedObjectContext+Querying.swift index 3bce69f..2eaca52 100644 --- a/CoreStore/Internal/NSManagedObjectContext+Querying.swift +++ b/CoreStore/Internal/NSManagedObjectContext+Querying.swift @@ -52,16 +52,24 @@ internal extension NSManagedObjectContext { } var fetchResults: [T]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T] + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) as? [T] + } + catch { + + fetchError = error as NSError + } } if fetchResults == nil { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -87,16 +95,24 @@ internal extension NSManagedObjectContext { } var fetchResults: [T]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T] + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) as? [T] + } + catch { + + fetchError = error as NSError + } } if fetchResults == nil { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -128,7 +144,8 @@ internal extension NSManagedObjectContext { CoreStore.handleError( error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + "Failed executing fetch request." + ) return nil } @@ -154,16 +171,24 @@ internal extension NSManagedObjectContext { } var fetchResults: [NSManagedObjectID]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObjectID] + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID] + } + catch { + + fetchError = error as NSError + } } if fetchResults == nil { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -189,16 +214,24 @@ internal extension NSManagedObjectContext { } var fetchResults: [NSManagedObjectID]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObjectID] + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID] + } + catch { + + fetchError = error as NSError + } } if fetchResults == nil { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -225,26 +258,32 @@ internal extension NSManagedObjectContext { } var numberOfDeletedObjects: Int? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { autoreleasepool { - if let fetchResults = self.executeFetchRequest(fetchRequest, error: &error) as? [T] { + do { - numberOfDeletedObjects = fetchResults.count + let fetchResults = try self.executeFetchRequest(fetchRequest) as? [T] ?? [] for object in fetchResults { self.deleteObject(object) } + numberOfDeletedObjects = fetchResults.count + } + catch { + + fetchError = error as NSError } } } if numberOfDeletedObjects == nil { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -271,10 +310,17 @@ internal extension NSManagedObjectContext { } var fetchResults: [AnyObject]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) + } + catch { + + fetchError = error as NSError + } } if let fetchResults = fetchResults { @@ -287,8 +333,9 @@ internal extension NSManagedObjectContext { } CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } @@ -312,10 +359,17 @@ internal extension NSManagedObjectContext { } var fetchResults: [AnyObject]? - var error: NSError? + var fetchError: NSError? self.performBlockAndWait { - fetchResults = self.executeFetchRequest(fetchRequest, error: &error) + do { + + fetchResults = try self.executeFetchRequest(fetchRequest) + } + catch { + + fetchError = error as NSError + } } if let fetchResults = fetchResults { @@ -323,8 +377,9 @@ internal extension NSManagedObjectContext { } CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed executing fetch request.") + fetchError ?? NSError(coreStoreErrorCode: .UnknownError), + "Failed executing fetch request." + ) return nil } } diff --git a/CoreStore/Internal/NSManagedObjectContext+Transaction.swift b/CoreStore/Internal/NSManagedObjectContext+Transaction.swift index 4f3173d..28777dd 100644 --- a/CoreStore/Internal/NSManagedObjectContext+Transaction.swift +++ b/CoreStore/Internal/NSManagedObjectContext+Transaction.swift @@ -68,44 +68,43 @@ internal extension NSManagedObjectContext { internal func saveSynchronously() -> SaveResult { var result = SaveResult(hasChanges: false) - self.performBlockAndWait { - [unowned self] () -> Void in + + self.performBlockAndWait { [unowned self] () -> Void in if !self.hasChanges { return } - var saveError: NSError? - if self.save(&saveError) { + do { - if self.shouldCascadeSavesToParent { - - if let parentContext = self.parentContext { - - switch parentContext.saveSynchronously() { - - case .Success(let hasChanges): - result = SaveResult(hasChanges: true) - case .Failure(let error): - result = SaveResult(error) - } - return - } - } - - result = SaveResult(hasChanges: true) + try self.save() } - else if let error = saveError { + catch { + let saveError = error as NSError CoreStore.handleError( - error, - "Failed to save <\(NSManagedObjectContext.self)>.") - result = SaveResult(error) + saveError, + "Failed to save \(typeName(NSManagedObjectContext))." + ) + result = SaveResult(saveError) + return + } + + if let parentContext = self.parentContext where self.shouldCascadeSavesToParent { + + switch parentContext.saveSynchronously() { + + case .Success: + result = SaveResult(hasChanges: true) + + case .Failure(let error): + result = SaveResult(error) + } } else { - result = SaveResult(hasChanges: false) + result = SaveResult(hasChanges: true) } } @@ -128,43 +127,35 @@ internal extension NSManagedObjectContext { return } - var saveError: NSError? - if self.save(&saveError) { + do { - if self.shouldCascadeSavesToParent { - - if let parentContext = self.parentContext { - - let result = parentContext.saveSynchronously() - if let completion = completion { - - GCDQueue.Main.async { - - completion(result: result) - } - } - return - } - } - - if let completion = completion { - - GCDQueue.Main.async { - - completion(result: SaveResult(hasChanges: true)) - } - } + try self.save() } - else if let error = saveError { + catch { + let saveError = error as NSError CoreStore.handleError( - error, - "Failed to save <\(NSManagedObjectContext.self)>.") + saveError, + "Failed to save \(typeName(NSManagedObjectContext))." + ) if let completion = completion { GCDQueue.Main.async { - completion(result: SaveResult(error)) + completion(result: SaveResult(saveError)) + } + } + return + } + + if let parentContext = self.parentContext where self.shouldCascadeSavesToParent { + + let result = parentContext.saveSynchronously() + if let completion = completion { + + GCDQueue.Main.async { + + completion(result: result) } } } @@ -172,7 +163,7 @@ internal extension NSManagedObjectContext { GCDQueue.Main.async { - completion(result: SaveResult(hasChanges: false)) + completion(result: SaveResult(hasChanges: true)) } } } diff --git a/CoreStore/Internal/NSManagedObjectModel+Setup.swift b/CoreStore/Internal/NSManagedObjectModel+Setup.swift index 50ce421..c9ddf00 100644 --- a/CoreStore/Internal/NSManagedObjectModel+Setup.swift +++ b/CoreStore/Internal/NSManagedObjectModel+Setup.swift @@ -33,25 +33,177 @@ internal extension NSManagedObjectModel { // MARK: Internal + private var modelFileURL: NSURL? { + + get { + + return self.modelVersionFileURL?.URLByDeletingLastPathComponent + } + } + + private(set) var currentModelVersion: String? { + + get { + + let value: NSString? = getAssociatedObjectForKey( + &PropertyKeys.currentModelVersion, + inObject: self + ) + return value as? String + } + set { + + setAssociatedCopiedObject( + newValue == nil ? nil : (newValue! as NSString), + forKey: &PropertyKeys.currentModelVersion, + inObject: self + ) + } + } + + private(set) var modelVersions: Set? { + + get { + + let value: NSSet? = getAssociatedObjectForKey( + &PropertyKeys.modelVersions, + inObject: self + ) + return value as? Set + } + set { + + setAssociatedCopiedObject( + newValue == nil ? nil : (newValue! as NSSet), + forKey: &PropertyKeys.modelVersions, + inObject: self + ) + } + } + func entityNameForClass(entityClass: AnyClass) -> String { return self.entityNameMapping[NSStringFromClass(entityClass)]! } - func configurationsForClass(entityClass: AnyClass) -> Set { + func mergedModels() -> [NSManagedObjectModel] { - return self.entityConfigurationsMapping[NSStringFromClass(entityClass)]! + return self.modelVersions?.map { self[$0] }.flatMap { $0 == nil ? [] : [$0!] } ?? [self] + } + + subscript(modelVersion: String) -> NSManagedObjectModel? { + + if modelVersion == self.currentModelVersion { + + return self + } + + guard let modelFileURL = self.modelFileURL, + let modelVersions = self.modelVersions + where modelVersions.contains(modelVersion) else { + + return nil + } + + let versionModelFileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false) + guard let model = NSManagedObjectModel(contentsOfURL: versionModelFileURL) else { + + return nil + } + + model.currentModelVersion = modelVersion + model.modelVersionFileURL = versionModelFileURL + model.modelVersions = modelVersions + return model + } + + class func fromBundle(bundle: NSBundle, modelName: String, modelVersion: String? = nil) -> NSManagedObjectModel { + + guard let modelFilePath = bundle.pathForResource(modelName, ofType: "momd") else { + + CoreStore.fatalError("Could not find \"\(modelName).momd\" from the bundle. \(bundle)") + } + + let modelFileURL = NSURL(fileURLWithPath: modelFilePath) + let versionInfoPlistURL = modelFileURL.URLByAppendingPathComponent("VersionInfo.plist", isDirectory: false) + + guard let versionInfo = NSDictionary(contentsOfURL: versionInfoPlistURL), + let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else { + + CoreStore.fatalError("Could not load \(typeName(NSManagedObjectModel)) metadata from path \"\(versionInfoPlistURL)\"." + ) + } + + let modelVersions = Set(versionHashes.keys) + let currentModelVersion: String + + if let modelVersion = modelVersion { + + precondition(modelVersions.contains(modelVersion)) + currentModelVersion = modelVersion + } + else { + + currentModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String ?? modelVersions.first! + } + + var modelVersionFileURL: NSURL? + for modelVersion in modelVersions { + + let fileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false) + + if modelVersion == currentModelVersion { + + modelVersionFileURL = fileURL + continue + } + + CoreStore.assert( + NSManagedObjectModel(contentsOfURL: fileURL) != nil, + "Could not find the \"\(modelVersion).mom\" version file for the model at URL \"\(modelFileURL)\"." + ) + } + + if let modelVersionFileURL = modelVersionFileURL, + let rootModel = NSManagedObjectModel(contentsOfURL: modelVersionFileURL) { + + rootModel.modelVersionFileURL = modelVersionFileURL + rootModel.modelVersions = modelVersions + rootModel.currentModelVersion = currentModelVersion + return rootModel + } + + CoreStore.fatalError("Could not create an \(typeName(NSManagedObjectModel)) from the model at URL \"\(modelFileURL)\".") } // MARK: Private - - internal var entityNameMapping: [String: String] { + private var modelVersionFileURL: NSURL? { get { - if let mapping: NSDictionary? = getAssociatedObjectForKey(&PropertyKeys.entityNameMapping, inObject: self) { + let value: NSURL? = getAssociatedObjectForKey( + &PropertyKeys.modelVersionFileURL, + inObject: self + ) + return value + } + set { + + setAssociatedCopiedObject( + newValue, + forKey: &PropertyKeys.modelVersionFileURL, + inObject: self + ) + } + } + + private var entityNameMapping: [String: String] { + + get { + + if let mapping: NSDictionary = getAssociatedObjectForKey(&PropertyKeys.entityNameMapping, inObject: self) { return mapping as! [String: String] } @@ -75,25 +227,12 @@ internal extension NSManagedObjectModel { } } - private lazy var entityConfigurationsMapping: [String: Set] = { - [unowned self] in - - return self.configurations.reduce([String: Set]()) { - (var mapping, configuration) -> [String: Set] in - - return (self.entitiesForConfiguration(configuration) ?? []).reduce(mapping) { - (var mapping, entityDescription) -> [String: Set] in - - let className = entityDescription.managedObjectClassName - mapping[className]?.insert(configuration) - return mapping - } - } - }() - private struct PropertyKeys { static var entityNameMapping: Void? - static var entityConfigurationsMapping: Void? + + static var modelVersionFileURL: Void? + static var modelVersions: Void? + static var currentModelVersion: Void? } } diff --git a/CoreStore/Internal/NotificationObserver.swift b/CoreStore/Internal/NotificationObserver.swift index ad4d899..b663a41 100644 --- a/CoreStore/Internal/NotificationObserver.swift +++ b/CoreStore/Internal/NotificationObserver.swift @@ -36,7 +36,7 @@ internal final class NotificationObserver { let object: AnyObject? let observer: NSObjectProtocol - init(notificationName: String, object: AnyObject?, closure: (note: NSNotification!) -> Void) { + init(notificationName: String, object: AnyObject?, closure: (note: NSNotification) -> Void) { self.notificationName = notificationName self.object = object diff --git a/CoreStore/Internal/RootManagedObjectModel.swift b/CoreStore/Internal/RootManagedObjectModel.swift deleted file mode 100644 index f9246e4..0000000 --- a/CoreStore/Internal/RootManagedObjectModel.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// RootManagedObjectModel.swift -// CoreStore -// -// Created by John Rommel Estropia on 2015/07/04. -// Copyright © 2015 John Rommel Estropia. All rights reserved. -// - -import UIKit - -class RootManagedObjectModel: NSManagedObjectModel { - -} diff --git a/CoreStore/Logging/CoreStore+Logging.swift b/CoreStore/Logging/CoreStore+Logging.swift index c0284f0..78653e4 100644 --- a/CoreStore/Logging/CoreStore+Logging.swift +++ b/CoreStore/Logging/CoreStore+Logging.swift @@ -60,7 +60,8 @@ public extension CoreStore { message: message, fileName: fileName, lineNumber: lineNumber, - functionName: functionName) + functionName: functionName + ) } internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) { @@ -70,6 +71,17 @@ public extension CoreStore { message: message, fileName: fileName, lineNumber: lineNumber, - functionName: functionName) + functionName: functionName + ) + } + + @noreturn internal static func fatalError(message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) { + + self.logger.fatalError( + message, + fileName: fileName, + lineNumber: lineNumber, + functionName: functionName + ) } } diff --git a/CoreStore/Logging/CoreStoreLogger.swift b/CoreStore/Logging/CoreStoreLogger.swift index fdf2756..cf0401b 100644 --- a/CoreStore/Logging/CoreStoreLogger.swift +++ b/CoreStore/Logging/CoreStoreLogger.swift @@ -56,7 +56,7 @@ public protocol CoreStoreLogger { :lineNumber: the source line number :functionName: the source function name */ - func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) + func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) /** Handles errors sent by the `CoreStore` framework. @@ -67,7 +67,7 @@ public protocol CoreStoreLogger { :lineNumber: the source line number :functionName: the source function name */ - func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) + func handleError(error error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) /** Handles assertions made throughout the `CoreStore` framework. @@ -79,6 +79,16 @@ public protocol CoreStoreLogger { :functionName: the source function name */ func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) + + /** + Handles fatal errors made throughout the `CoreStore` framework. Implementations should guarantee that the method does not return, either by calling fatalError() or preconditionFailure(), or by raising an exception. + + :message: the error message + :fileName: the source file name + :lineNumber: the source line number + :functionName: the source function name + */ + @noreturn func fatalError(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) } @@ -98,3 +108,9 @@ internal func typeName(value: AnyClass) -> String { return "<\(value)>" } + +internal func typeName(name: String?) -> String { + + let typeName = name ?? "unknown" + return "<\(typeName)>" +} diff --git a/CoreStore/Logging/DefaultLogger.swift b/CoreStore/Logging/DefaultLogger.swift index ca2907f..b18c007 100644 --- a/CoreStore/Logging/DefaultLogger.swift +++ b/CoreStore/Logging/DefaultLogger.swift @@ -31,15 +31,15 @@ import Foundation /** The `DefaultLogger` is a basic implementation of the `CoreStoreLogger` protocol. -- The `log(...)` method calls `println(...)` to print the level, source file name, line number, function name, and the log message. -- The `handleError(...)` method calls `println(...)` to print the source file name, line number, function name, and the error message. +- The `log(...)` method calls `print(...)` to print the level, source file name, line number, function name, and the log message. +- The `handleError(...)` method calls `print(...)` to print the source file name, line number, function name, and the error message. - The `assert(...)` method calls `assert(...)` on the arguments. */ public final class DefaultLogger: CoreStoreLogger { public init() { } - public func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + public func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { #if DEBUG let levelString: String @@ -49,14 +49,14 @@ public final class DefaultLogger: CoreStoreLogger { case .Warning: levelString = "Warning" case .Fatal: levelString = "Fatal" } - Swift.println("[CoreStore:\(levelString)] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n") + Swift.print("[CoreStore:\(levelString)] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n") #endif } - public func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + public func handleError(error error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { #if DEBUG - Swift.println("[CoreStore:Error] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message): \(error)\n") + Swift.print("[CoreStore:Error] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message): \(error)\n") #endif } @@ -66,4 +66,9 @@ public final class DefaultLogger: CoreStoreLogger { Swift.assert(condition, message, file: fileName, line: numericCast(lineNumber)) #endif } + + @noreturn public func fatalError(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + + Swift.fatalError("[CoreStore:Abort] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n") + } } diff --git a/CoreStore/Migrating/MigrationChain.swift b/CoreStore/Migrating/MigrationChain.swift index 3cc563e..6cb899b 100644 --- a/CoreStore/Migrating/MigrationChain.swift +++ b/CoreStore/Migrating/MigrationChain.swift @@ -42,7 +42,11 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D public func nextVersionFrom(version: String) -> String? { - return self.versionTree[version] + if let nextVersion = self.versionTree[version] where nextVersion != version { + + return nextVersion + } + return nil } @@ -65,6 +69,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D self.leafVersions = [value] } + // MARK: ExtendedGraphemeClusterLiteralConvertible public init(extendedGraphemeClusterLiteral value: String) { @@ -126,8 +131,8 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D } self.versionTree = versionTree - self.rootVersions = Set(flatMap([elements.first]) { $0 == nil ? [] : [$0!] }) - self.leafVersions = Set(flatMap([elements.last]) { $0 == nil ? [] : [$0!] }) + self.rootVersions = Set([elements.first].flatMap { $0 == nil ? [] : [$0!] }) + self.leafVersions = Set([elements.last].flatMap { $0 == nil ? [] : [$0!] }) } diff --git a/CoreStore/Observing/CoreStore+Observing.swift b/CoreStore/Observing/CoreStore+Observing.swift index 9073768..ec3f9b5 100644 --- a/CoreStore/Observing/CoreStore+Observing.swift +++ b/CoreStore/Observing/CoreStore+Observing.swift @@ -36,8 +36,8 @@ public extension CoreStore { /** Using the `defaultStack`, creates a `ObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`. - :param: object the `NSManagedObject` to observe changes from - :returns: a `ObjectMonitor` that monitors changes to `object` + - parameter object: the `NSManagedObject` to observe changes from + - returns: a `ObjectMonitor` that monitors changes to `object` */ public static func monitorObject(object: T) -> ObjectMonitor { @@ -47,9 +47,9 @@ public extension CoreStore { /** Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. - :param: from a `From` clause indicating the entity type - :param: 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 + - 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. + - returns: a `ListMonitor` instance that monitors changes to the list */ public static func monitorList(from: From, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ListMonitor { @@ -59,9 +59,9 @@ public extension CoreStore { /** Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. - :param: from a `From` clause indicating the entity type - :param: 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 + - 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. + - returns: a `ListMonitor` instance that monitors changes to the list */ public static func monitorList(from: From, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ListMonitor { @@ -71,10 +71,10 @@ public extension CoreStore { /** Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. - :param: from a `From` clause indicating the entity type - :param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - :param: 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 + - parameter from: a `From` clause indicating the entity type + - 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. + - returns: a `ListMonitor` instance that monitors changes to the list */ public static func monitorSectionedList(from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor { @@ -84,10 +84,10 @@ public extension CoreStore { /** Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list. - :param: from a `From` clause indicating the entity type - :param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - :param: 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 + - parameter from: a `From` clause indicating the entity type + - 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. + - returns: a `ListMonitor` instance that monitors changes to the list */ public static func monitorSectionedList(from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor { diff --git a/CoreStore/Observing/ListMonitor.swift b/CoreStore/Observing/ListMonitor.swift index d74a315..b32055e 100644 --- a/CoreStore/Observing/ListMonitor.swift +++ b/CoreStore/Observing/ListMonitor.swift @@ -74,32 +74,32 @@ public final class ListMonitor { /** Accesses the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `addObserver(_:)`. - :param: index the index of the object. Using an index above the valid range will throw an exception. + - parameter index: the index of the object. Using an index above the valid range will throw an exception. */ public subscript(index: Int) -> T { - return self.fetchedResultsController.objectAtIndexPath(NSIndexPath(forItem: index, inSection: 0)) as! T - } - - /** - Accesses the object at the given `NSIndexPath`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`. - - :param: indexPath the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will throw an exception. - */ - public subscript(indexPath: NSIndexPath) -> T { - - return self.fetchedResultsController.objectAtIndexPath(indexPath) as! T + return self[0, index] } /** Accesses the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`. - :param: sectionIndex the section index for the object. Using a `sectionIndex` with an invalid range will throw an exception. - :param: itemIndex the index for the object within the section. Using an `itemIndex` with an invalid range will throw an exception. + - parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will throw an exception. + - parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will throw an exception. */ public subscript(sectionIndex: Int, itemIndex: Int) -> T { - return self.fetchedResultsController.objectAtIndexPath(NSIndexPath(forItem: itemIndex, inSection: sectionIndex)) as! T + return self[NSIndexPath(forItem: itemIndex, inSection: sectionIndex)] + } + + /** + Accesses the object at the given `NSIndexPath`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`. + + - parameter indexPath: the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will throw an exception. + */ + public subscript(indexPath: NSIndexPath) -> T { + + return self.fetchedResultsController.objectAtIndexPath(indexPath) as! T } /** @@ -113,21 +113,21 @@ public final class ListMonitor { /** Returns the number of objects in the specified section - :param: section the section index + - parameter section: the section index */ public func numberOfObjectsInSection(section: Int) -> Int { - return (self.fetchedResultsController.sections?[section] as? NSFetchedResultsSectionInfo)?.numberOfObjects ?? 0 + return self.fetchedResultsController.sections?[section].numberOfObjects ?? 0 } /** Returns the `NSFetchedResultsSectionInfo` for the specified section - :param: section the section index + - parameter section: the section index */ public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo { - return self.fetchedResultsController.sections![section] as! NSFetchedResultsSectionInfo + return self.fetchedResultsController.sections![section] } /** @@ -139,11 +139,14 @@ public final class ListMonitor { Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. - :param: observer a `ListObserver` to send change notifications to + - parameter observer: a `ListObserver` to send change notifications to */ public func addObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to add an observer of type \(typeName(observer)) outside the main thread." + ) self.removeObserver(observer) @@ -182,11 +185,14 @@ public final class ListMonitor { Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. - :param: observer a `ListObjectObserver` to send change notifications to + - parameter observer: a `ListObjectObserver` to send change notifications to */ public func addObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to add an observer of type \(typeName(observer)) outside the main thread." + ) self.removeObserver(observer) @@ -291,11 +297,14 @@ public final class ListMonitor { Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. - :param: observer a `ListSectionObserver` to send change notifications to + - parameter observer: a `ListSectionObserver` to send change notifications to */ public func addObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to add an observer of type \(typeName(observer)) outside the main thread." + ) self.removeObserver(observer) @@ -429,11 +438,14 @@ public final class ListMonitor { For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread. - :param: observer a `ListObserver` to unregister notifications to + - parameter observer: a `ListObserver` to unregister notifications to */ public func removeObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to remove an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to remove an observer of type \(typeName(observer)) outside the main thread." + ) let nilValue: AnyObject? = nil setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeList, inObject: observer) @@ -492,12 +504,16 @@ public final class ListMonitor { fetchedResultsControllerDelegate.handler = self fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController - var error: NSError? - if !fetchedResultsController.performFetch(&error) { + do { + + try fetchedResultsController.performFetch() + } + catch { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to perform fetch on <\(NSFetchedResultsController.self)>.") + error as NSError, + "Failed to perform fetch on \(typeName(NSFetchedResultsController))." + ) } } @@ -705,31 +721,31 @@ private protocol FetchedResultsControllerHandler: class { // MARK: - FetchedResultsControllerDelegate -private final class FetchedResultsControllerDelegate: NSFetchedResultsControllerDelegate { +private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate { // MARK: NSFetchedResultsControllerDelegate - @objc func controllerWillChangeContent(controller: NSFetchedResultsController) { + @objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) { self.handler?.controllerWillChangeContent(controller) } - @objc func controllerDidChangeContent(controller: NSFetchedResultsController) { + @objc dynamic func controllerDidChangeContent(controller: NSFetchedResultsController) { self.handler?.controllerDidChangeContent(controller) } - @objc func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { + @objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: NSManagedObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath) } - @objc func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { + @objc dynamic func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { self.handler?.controller(controller, didChangeSection: sectionInfo, atIndex: sectionIndex, forChangeType: type) } - @objc func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? { + @objc dynamic func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String) -> String? { return self.handler?.controller(controller, sectionIndexTitleForSectionName: sectionName) } diff --git a/CoreStore/Observing/ListObserver.swift b/CoreStore/Observing/ListObserver.swift index dc6b29b..7a9581a 100644 --- a/CoreStore/Observing/ListObserver.swift +++ b/CoreStore/Observing/ListObserver.swift @@ -48,14 +48,14 @@ public protocol ListObserver: class { /** Handles processing just before a change to the observed list occurs - :param: monitor the `ListMonitor` monitoring the list being observed + - parameter monitor: the `ListMonitor` monitoring the list being observed */ func listMonitorWillChange(monitor: ListMonitor) /** Handles processing right after a change to the observed list occurs - :param: monitor the `ListMonitor` monitoring the object being observed + - parameter monitor: the `ListMonitor` monitoring the object being observed */ func listMonitorDidChange(monitor: ListMonitor) } @@ -77,37 +77,37 @@ public protocol ListObjectObserver: ListObserver { /** Notifies that an object was inserted to the specified `NSIndexPath` in the list - :param: monitor the `ListMonitor` monitoring the list being observed - :param: object the entity type for the inserted object - :param: indexPath the new `NSIndexPath` for the inserted object + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter object: the entity type for the inserted object + - parameter indexPath: the new `NSIndexPath` for the inserted object */ func listMonitor(monitor: ListMonitor, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath) /** Notifies that an object was deleted from the specified `NSIndexPath` in the list - :param: monitor the `ListMonitor` monitoring the list being observed - :param: object the entity type for the deleted object - :param: indexPath the `NSIndexPath` for the deleted object + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter object: the entity type for the deleted object + - parameter indexPath: the `NSIndexPath` for the deleted object */ func listMonitor(monitor: ListMonitor, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath) /** Notifies that an object at the specified `NSIndexPath` was updated - :param: monitor the `ListMonitor` monitoring the list being observed - :param: object the entity type for the updated object - :param: indexPath the `NSIndexPath` for the updated object + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter object: the entity type for the updated object + - parameter indexPath: the `NSIndexPath` for the updated object */ func listMonitor(monitor: ListMonitor, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath) /** Notifies that an object's index changed - :param: monitor the `ListMonitor` monitoring the list being observed - :param: object the entity type for the moved object - :param: fromIndexPath the previous `NSIndexPath` for the moved object - :param: toIndexPath the new `NSIndexPath` for the moved object + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter object: the entity type for the moved object + - parameter fromIndexPath: the previous `NSIndexPath` for the moved object + - parameter toIndexPath: the new `NSIndexPath` for the moved object */ func listMonitor(monitor: ListMonitor, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) } @@ -130,18 +130,18 @@ public protocol ListSectionObserver: ListObjectObserver { /** Notifies that a section was inserted at the specified index - :param: monitor the `ListMonitor` monitoring the list being observed - :param: sectionInfo the `NSFetchedResultsSectionInfo` for the inserted section - :param: sectionIndex the new section index for the new section + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the inserted section + - parameter sectionIndex: the new section index for the new section */ func listMonitor(monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) /** Notifies that a section was inserted at the specified index - :param: monitor the `ListMonitor` monitoring the list being observed - :param: sectionInfo the `NSFetchedResultsSectionInfo` for the deleted section - :param: sectionIndex the previous section index for the deleted section + - parameter monitor: the `ListMonitor` monitoring the list being observed + - parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the deleted section + - parameter sectionIndex: the previous section index for the deleted section */ func listMonitor(monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) } diff --git a/CoreStore/Observing/ObjectMonitor.swift b/CoreStore/Observing/ObjectMonitor.swift index e62fa15..6ac31ca 100644 --- a/CoreStore/Observing/ObjectMonitor.swift +++ b/CoreStore/Observing/ObjectMonitor.swift @@ -83,11 +83,14 @@ public final class ObjectMonitor { Calling `addObserver(_:)` multiple times on the same observer is safe, as `ObjectMonitor` unregisters previous notifications to the observer before re-registering them. - :param: observer an `ObjectObserver` to send change notifications to + - parameter observer: an `ObjectObserver` to send change notifications to */ public func addObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to add an observer of type \(typeName(observer)) outside the main thread." + ) self.removeObserver(observer) @@ -95,9 +98,9 @@ public final class ObjectMonitor { &NotificationKey.willChangeObject, name: ObjectMonitorWillChangeObjectNotification, toObserver: observer, - callback: { [weak self, weak observer] (monitor) -> Void in + callback: { [weak observer] (monitor) -> Void in - if let strongSelf = self, let object = strongSelf.object, let observer = observer { + if let object = monitor.object, let observer = observer { observer.objectMonitor(monitor, willUpdateObject: object) } @@ -107,9 +110,9 @@ public final class ObjectMonitor { &NotificationKey.didDeleteObject, name: ObjectMonitorDidDeleteObjectNotification, toObserver: observer, - callback: { [weak self, weak observer] (monitor, object) -> Void in + callback: { [weak observer] (monitor, object) -> Void in - if let strongSelf = self, let observer = observer { + if let observer = observer { observer.objectMonitor(monitor, didDeleteObject: object) } @@ -124,15 +127,15 @@ public final class ObjectMonitor { if let strongSelf = self, let observer = observer { let previousCommitedAttributes = strongSelf.lastCommittedAttributes - let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [NSString: NSObject] + let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject] - var changedKeys = Set() - for key in currentCommitedAttributes.keys { + let changedKeys = currentCommitedAttributes.keys.reduce(Set()) { (var changedKeys, key) -> Set in if previousCommitedAttributes[key] != currentCommitedAttributes[key] { - changedKeys.insert(key as String) + changedKeys.insert(key) } + return changedKeys } strongSelf.lastCommittedAttributes = currentCommitedAttributes @@ -151,11 +154,14 @@ public final class ObjectMonitor { For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread. - :param: observer an `ObjectObserver` to unregister notifications to + - parameter observer: an `ObjectObserver` to unregister notifications to */ public func removeObserver(observer: U) { - CoreStore.assert(NSThread.isMainThread(), "Attempted to remove an observer of type \(typeName(observer)) outside the main thread.") + CoreStore.assert( + NSThread.isMainThread(), + "Attempted to remove an observer of type \(typeName(observer)) outside the main thread." + ) let nilValue: AnyObject? = nil setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeObject, inObject: observer) @@ -197,15 +203,20 @@ public final class ObjectMonitor { fetchedResultsControllerDelegate.handler = self fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController - var error: NSError? - if !fetchedResultsController.performFetch(&error) { + + do { + + try fetchedResultsController.performFetch() + } + catch { CoreStore.handleError( - error ?? NSError(coreStoreErrorCode: .UnknownError), - "Failed to perform fetch on <\(NSFetchedResultsController.self)>.") + error as NSError, + "Failed to perform fetch for \(typeName(NSFetchedResultsController))." + ) } - self.lastCommittedAttributes = (self.object?.committedValuesForKeys(nil) as? [NSString: NSObject]) ?? [:] + self.lastCommittedAttributes = (self.object?.committedValuesForKeys(nil) as? [String: NSObject]) ?? [:] } @@ -214,7 +225,7 @@ public final class ObjectMonitor { private let originalObjectID: NSManagedObjectID private let fetchedResultsController: NSFetchedResultsController private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate - private var lastCommittedAttributes = [NSString: NSObject]() + private var lastCommittedAttributes = [String: NSObject]() private weak var parentStack: DataStack? private func registerChangeNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor) -> Void) { @@ -313,16 +324,16 @@ private protocol FetchedResultsControllerHandler: class { // MARK: - FetchedResultsControllerDelegate -private final class FetchedResultsControllerDelegate: NSFetchedResultsControllerDelegate { +private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate { // MARK: NSFetchedResultsControllerDelegate - @objc func controllerWillChangeContent(controller: NSFetchedResultsController) { + @objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) { self.handler?.controllerWillChangeContent(controller) } - @objc func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { + @objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: NSManagedObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath) } diff --git a/CoreStore/Observing/ObjectObserver.swift b/CoreStore/Observing/ObjectObserver.swift index 26de479..40bcbc6 100644 --- a/CoreStore/Observing/ObjectObserver.swift +++ b/CoreStore/Observing/ObjectObserver.swift @@ -45,25 +45,25 @@ public protocol ObjectObserver: class { /** Handles processing just before a change to the observed `object` occurs - :param: monitor the `ObjectMonitor` monitoring the object being observed - :param: object the `NSManagedObject` instance being observed + - parameter monitor: the `ObjectMonitor` monitoring the object being observed + - parameter object: the `NSManagedObject` instance being observed */ func objectMonitor(monitor: ObjectMonitor, willUpdateObject object: EntityType) /** Handles processing right after a change to the observed `object` occurs - :param: monitor the `ObjectMonitor` monitoring the object being observed - :param: object the `NSManagedObject` instance being observed - :param: 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. + - parameter monitor: the `ObjectMonitor` monitoring the object being observed + - parameter object: the `NSManagedObject` 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: EntityType, changedPersistentKeys: Set) /** Handles processing right after `object` is deleted - :param: monitor the `ObjectMonitor` monitoring the object being observed - :param: object the `NSManagedObject` instance being observed + - parameter monitor: the `ObjectMonitor` monitoring the object being observed + - parameter object: the `NSManagedObject` instance being observed */ func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: EntityType) } diff --git a/CoreStore/Observing/SectionBy.swift b/CoreStore/Observing/SectionBy.swift index a203c1d..4a41b87 100644 --- a/CoreStore/Observing/SectionBy.swift +++ b/CoreStore/Observing/SectionBy.swift @@ -45,7 +45,7 @@ public struct SectionBy { /** Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections - :param: sectionKeyPath the key path to use to group the objects into sections + - parameter sectionKeyPath: the key path to use to group the objects into sections */ public init(_ sectionKeyPath: KeyPath) { @@ -55,8 +55,8 @@ public struct SectionBy { /** Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name - :param: sectionKeyPath the key path to use to group the objects into sections - :param: sectionIndexTransformer a closure to transform the value for the key path to an appropriate section name + - 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: (sectionName: String?) -> String?) { diff --git a/CoreStore/Saving and Processing/AsynchronousDataTransaction.swift b/CoreStore/Saving and Processing/AsynchronousDataTransaction.swift index 3671ec5..144faf6 100644 --- a/CoreStore/Saving and Processing/AsynchronousDataTransaction.swift +++ b/CoreStore/Saving and Processing/AsynchronousDataTransaction.swift @@ -40,12 +40,18 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Saves the transaction changes asynchronously. This method should not be used after the `commit()` method was already called once. - :param: completion the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. + - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. */ public func commit(completion: (result: SaveResult) -> Void) { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") - CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to commit a \(typeName(self)) outside its designated queue." + ) + CoreStore.assert( + !self.isCommitted, + "Attempted to commit a \(typeName(self)) more than once." + ) self.isCommitted = true let semaphore = GCDSemaphore(0) @@ -63,8 +69,14 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { */ public func commit() { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") - CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to commit a \(typeName(self)) outside its designated queue." + ) + CoreStore.assert( + !self.isCommitted, + "Attempted to commit a \(typeName(self)) more than once." + ) self.isCommitted = true self.result = self.context.saveSynchronously() @@ -73,13 +85,19 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once. - :param: closure the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - :returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously */ public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to begin a child transaction from a \(typeName(self)) outside its designated queue.") - CoreStore.assert(!self.isCommitted, "Attempted to begin a child transaction from an already committed \(typeName(self)).") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to begin a child transaction from a \(typeName(self)) outside its designated queue." + ) + CoreStore.assert( + !self.isCommitted, + "Attempted to begin a child transaction from an already committed \(typeName(self))." + ) return SynchronousDataTransaction( mainContext: self.context, @@ -93,12 +111,15 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Creates a new `NSManagedObject` with the specified entity type. - :param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - :returns: a new `NSManagedObject` instance of the specified entity type. + - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - returns: a new `NSManagedObject` instance of the specified entity type. */ public override func create(into: Into) -> T { - CoreStore.assert(!self.isCommitted, "Attempted to create an entity of type <\(T.self)> from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to create an entity of type \(typeName(T)) from an already committed \(typeName(self))." + ) return super.create(into) } @@ -106,12 +127,15 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. - :param: object the `NSManagedObject` type to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter object: the `NSManagedObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject`. */ public override func edit(object: T?) -> T? { - CoreStore.assert(!self.isCommitted, "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self))." + ) return super.edit(object) } @@ -119,13 +143,16 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `commit()` method was already called once. - :param: into an `Into` clause specifying the entity type - :param: objectID the `NSManagedObjectID` for the object to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter into: an `Into` clause specifying the entity type + - parameter objectID: the `NSManagedObjectID` for the object to be edited + - returns: an editable proxy for the specified `NSManagedObject`. */ public override func edit(into: Into, _ objectID: NSManagedObjectID) -> T? { - CoreStore.assert(!self.isCommitted, "Attempted to update an entity of type <\(T.self)> from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to update an entity of type \(typeName(T)) from an already committed \(typeName(self))." + ) return super.edit(into, objectID) } @@ -133,11 +160,14 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Deletes a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. - :param: object the `NSManagedObject` type to be deleted + - parameter object: the `NSManagedObject` type to be deleted */ public override func delete(object: NSManagedObject?) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self))." + ) super.delete(object) } @@ -145,13 +175,16 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: object1 the `NSManagedObject` type to be deleted - :param: object2 another `NSManagedObject` type to be deleted - :param: objects other `NSManagedObject`s type to be deleted + - parameter object1: the `NSManagedObject` type to be deleted + - parameter object2: another `NSManagedObject` type to be deleted + - parameter objects: other `NSManagedObject`s type to be deleted */ public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entities from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entities from an already committed \(typeName(self))." + ) super.delete([object1, object2] + objects) } @@ -159,11 +192,14 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: objects the `NSManagedObject`s type to be deleted + - parameter objects: the `NSManagedObject`s type to be deleted */ public override func delete(objects: [NSManagedObject?]) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entities from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entities from an already committed \(typeName(self))." + ) super.delete(objects) } @@ -173,7 +209,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { */ public override func rollback() { - CoreStore.assert(!self.isCommitted, "Attempted to rollback an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to rollback an already committed \(typeName(self))." + ) super.rollback() } @@ -195,7 +234,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { self.closure(transaction: self) if !self.isCommitted && self.hasChanges { - CoreStore.log(.Warning, message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded.") + CoreStore.log( + .Warning, + message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded." + ) } } } @@ -205,9 +247,13 @@ public final class AsynchronousDataTransaction: BaseDataTransaction { self.transactionQueue.sync { self.closure(transaction: self) + if !self.isCommitted && self.hasChanges { - CoreStore.log(.Warning, message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded.") + CoreStore.log( + .Warning, + message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded." + ) } } return self.result diff --git a/CoreStore/Saving and Processing/BaseDataTransaction.swift b/CoreStore/Saving and Processing/BaseDataTransaction.swift index bb5ea0e..671e679 100644 --- a/CoreStore/Saving and Processing/BaseDataTransaction.swift +++ b/CoreStore/Saving and Processing/BaseDataTransaction.swift @@ -48,62 +48,68 @@ public /*abstract*/ class BaseDataTransaction { /** Creates a new `NSManagedObject` with the specified entity type. - :param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - :returns: a new `NSManagedObject` instance of the specified entity type. + - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - returns: a new `NSManagedObject` instance of the specified entity type. */ public func create(into: Into) -> T { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to create an entity of type <\(T.self)> outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to create an entity of type \(typeName(T)) outside its designated queue." + ) let context = self.context let entityClass = (into.entityClass as! NSManagedObject.Type) - let object = entityClass.createInContext(context) as! T - if into.inferStoreIfPossible { switch context.parentStack!.persistentStoreForEntityClass(entityClass, configuration: nil, inferStoreIfPossible: true) { - case (.Some(let persistentStore), _): + case (let persistentStore?, _): + let object = entityClass.createInContext(context) as! T context.assignObject(object, toPersistentStore: persistentStore) + return object case (.None, true): - CoreStore.assert(false, "Attempted to create an entity of type <\(entityClass)> with ambiguous destination persistent store, but the configuration name was not specified.") + CoreStore.fatalError("Attempted to create an entity of type \(typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.") default: - CoreStore.assert(false, "Attempted to create an entity of type <\(entityClass)>, but a destination persistent store containing the entity type could not be found.") + CoreStore.fatalError("Attempted to create an entity of type \(typeName(entityClass)), but a destination persistent store containing the entity type could not be found.") } } else { switch context.parentStack!.persistentStoreForEntityClass(entityClass, configuration: into.configuration, inferStoreIfPossible: false) { - case (.Some(let persistentStore), _): + case (let persistentStore?, _): + let object = entityClass.createInContext(context) as! T context.assignObject(object, toPersistentStore: persistentStore) + return object default: if let configuration = into.configuration { - CoreStore.assert(false, "Attempted to create an entity of type <\(entityClass)> into the configuration \"\(configuration)\", which it doesn't belong to.") + CoreStore.fatalError("Attempted to create an entity of type \(typeName(entityClass)) into the configuration \"\(configuration)\", which it doesn't belong to.") } else { - CoreStore.assert(false, "Attempted to create an entity of type <\(entityClass)> into the default configuration, which it doesn't belong to.") + CoreStore.fatalError("Attempted to create an entity of type \(typeName(entityClass)) into the default configuration, which it doesn't belong to.") } } } - - return object } /** Returns an editable proxy of a specified `NSManagedObject`. - :param: object the `NSManagedObject` type to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter object: the `NSManagedObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject`. */ public func edit(object: T?) -> T? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to update an entity of type \(typeName(object)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to update an entity of type \(typeName(object)) outside its designated queue." + ) return object?.inContext(self.context) } @@ -111,14 +117,21 @@ public /*abstract*/ class BaseDataTransaction { /** Returns an editable proxy of the object with the specified `NSManagedObjectID`. - :param: into an `Into` clause specifying the entity type - :param: objectID the `NSManagedObjectID` for the object to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter into: an `Into` clause specifying the entity type + - 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? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to update an entity of type <\(T.self)> outside its designated queue.") - CoreStore.assert(into.inferStoreIfPossible || (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName, "Attempted to update an entity of type <\(T.self)> but the specified persistent store do not match the `NSManagedObjectID`.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to update an entity of type \(typeName(T)) outside its designated queue." + ) + CoreStore.assert( + into.inferStoreIfPossible + || (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName, + "Attempted to update an entity of type \(typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`." + ) return (into.entityClass as! NSManagedObject.Type).inContext(self.context, withObjectID: objectID) as? T } @@ -126,11 +139,14 @@ public /*abstract*/ class BaseDataTransaction { /** Deletes a specified `NSManagedObject`. - :param: object the `NSManagedObject` to be deleted + - parameter object: the `NSManagedObject` to be deleted */ public func delete(object: NSManagedObject?) { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to delete an entity outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to delete an entity outside its designated queue." + ) object?.inContext(self.context)?.deleteFromContext() } @@ -138,9 +154,9 @@ public /*abstract*/ class BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: object1 the `NSManagedObject` to be deleted - :param: object2 another `NSManagedObject` to be deleted - :param: objects other `NSManagedObject`s to be deleted + - parameter object1: the `NSManagedObject` to be deleted + - parameter object2: another `NSManagedObject` to be deleted + - parameter objects: other `NSManagedObject`s to be deleted */ public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { @@ -150,11 +166,14 @@ public /*abstract*/ class BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: objects the `NSManagedObject`s to be deleted + - parameter objects: the `NSManagedObject`s to be deleted */ public func delete(objects: [NSManagedObject?]) { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to delete entities outside their designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to delete entities outside their designated queue." + ) let context = self.context for object in objects { @@ -170,7 +189,10 @@ public /*abstract*/ class BaseDataTransaction { */ public func rollback() { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to rollback a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to rollback a \(typeName(self)) outside its designated queue." + ) self.context.reset() } diff --git a/CoreStore/Saving and Processing/CoreStore+Transaction.swift b/CoreStore/Saving and Processing/CoreStore+Transaction.swift index b2fd5b0..e51628f 100644 --- a/CoreStore/Saving and Processing/CoreStore+Transaction.swift +++ b/CoreStore/Saving and Processing/CoreStore+Transaction.swift @@ -35,7 +35,7 @@ public extension CoreStore { /** Using the `defaultStack`, begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made. - :param: closure the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. */ public static func beginAsynchronous(closure: (transaction: AsynchronousDataTransaction) -> Void) { @@ -45,8 +45,8 @@ public extension CoreStore { /** Using the `defaultStack`, begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made. - :param: closure the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - :returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously */ public static func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? { @@ -56,7 +56,7 @@ public extension CoreStore { /** Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. A detached transaction object should typically be only used from the main queue. - :returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made. + - returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made. */ public static func beginDetached() -> DetachedDataTransaction { diff --git a/CoreStore/Saving and Processing/DetachedDataTransaction.swift b/CoreStore/Saving and Processing/DetachedDataTransaction.swift index d577d03..db2851e 100644 --- a/CoreStore/Saving and Processing/DetachedDataTransaction.swift +++ b/CoreStore/Saving and Processing/DetachedDataTransaction.swift @@ -39,11 +39,14 @@ public final class DetachedDataTransaction: BaseDataTransaction { /** Saves the transaction changes asynchronously. For a `DetachedDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. - :param: completion the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. + - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. */ public func commit(completion: (result: SaveResult) -> Void) { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to commit a \(typeName(self)) outside its designated queue." + ) self.context.saveAsynchronouslyWithCompletion { (result) -> Void in diff --git a/CoreStore/Saving and Processing/Into.swift b/CoreStore/Saving and Processing/Into.swift index f0f916e..fecd936 100644 --- a/CoreStore/Saving and Processing/Into.swift +++ b/CoreStore/Saving and Processing/Into.swift @@ -68,7 +68,7 @@ public struct Into { let person = transaction.create(Into(MyPersonEntity)) - :param: entity the `NSManagedObject` type to be created + - parameter entity: the `NSManagedObject` type to be created */ public init(_ entity: T.Type) { @@ -80,7 +80,7 @@ public struct Into { /** Initializes an `Into` clause with the specified entity class. - :param: entityClass the `NSManagedObject` class type to be created + - parameter entityClass: the `NSManagedObject` class type to be created */ public init(_ entityClass: AnyClass) { @@ -95,7 +95,7 @@ public struct Into { let person = transaction.create(Into("Configuration1")) - :param: configuration the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. + - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. */ public init(_ configuration: String?) { @@ -110,8 +110,8 @@ public struct Into { let person = transaction.create(Into(MyPersonEntity.self, "Configuration1")) - :param: entity the `NSManagedObject` type to be created - :param: configuration the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. + - parameter entity: the `NSManagedObject` type to be created + - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. */ public init(_ entity: T.Type, _ configuration: String?) { @@ -126,8 +126,8 @@ public struct Into { let person = transaction.create(Into(MyPersonEntity.self, "Configuration1")) - :param: entityClass the `NSManagedObject` class type to be created - :param: configuration the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. + - parameter entityClass: the `NSManagedObject` class type to be created + - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. */ public init(_ entityClass: AnyClass, _ configuration: String?) { diff --git a/CoreStore/Saving and Processing/SaveResult.swift b/CoreStore/Saving and Processing/SaveResult.swift index ea140f7..13b49d4 100644 --- a/CoreStore/Saving and Processing/SaveResult.swift +++ b/CoreStore/Saving and Processing/SaveResult.swift @@ -91,9 +91,7 @@ public enum SaveResult { internal init(_ errorCode: CoreStoreErrorCode, userInfo: [NSObject: AnyObject]?) { - self.init(NSError( - coreStoreErrorCode: errorCode, - userInfo: userInfo)) + self.init(NSError(coreStoreErrorCode: errorCode, userInfo: userInfo)) } } diff --git a/CoreStore/Saving and Processing/SynchronousDataTransaction.swift b/CoreStore/Saving and Processing/SynchronousDataTransaction.swift index 47f3fa2..e50f363 100644 --- a/CoreStore/Saving and Processing/SynchronousDataTransaction.swift +++ b/CoreStore/Saving and Processing/SynchronousDataTransaction.swift @@ -42,8 +42,14 @@ public final class SynchronousDataTransaction: BaseDataTransaction { */ public func commit() { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") - CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to commit a \(typeName(self)) outside its designated queue." + ) + CoreStore.assert( + !self.isCommitted, + "Attempted to commit a \(typeName(self)) more than once." + ) self.isCommitted = true self.result = self.context.saveSynchronously() @@ -52,13 +58,19 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once. - :param: closure the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - :returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously */ public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? { - CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to begin a child transaction from a \(typeName(self)) outside its designated queue.") - CoreStore.assert(!self.isCommitted, "Attempted to begin a child transaction from an already committed \(typeName(self)).") + CoreStore.assert( + self.transactionQueue.isCurrentExecutionContext(), + "Attempted to begin a child transaction from a \(typeName(self)) outside its designated queue." + ) + CoreStore.assert( + !self.isCommitted, + "Attempted to begin a child transaction from an already committed \(typeName(self))." + ) return SynchronousDataTransaction( mainContext: self.context, @@ -72,12 +84,15 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Creates a new `NSManagedObject` with the specified entity type. - :param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - :returns: a new `NSManagedObject` instance of the specified entity type. + - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - returns: a new `NSManagedObject` instance of the specified entity type. */ public override func create(into: Into) -> T { - CoreStore.assert(!self.isCommitted, "Attempted to create an entity of type <\(T.self)> from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to create an entity of type \(typeName(T)) from an already committed \(typeName(self))." + ) return super.create(into) } @@ -85,12 +100,15 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. - :param: object the `NSManagedObject` type to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter object: the `NSManagedObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject`. */ public override func edit(object: T?) -> T? { - CoreStore.assert(!self.isCommitted, "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self))." + ) return super.edit(object) } @@ -98,13 +116,16 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `commit()` method was already called once. - :param: into an `Into` clause specifying the entity type - :param: objectID the `NSManagedObjectID` for the object to be edited - :returns: an editable proxy for the specified `NSManagedObject`. + - parameter into: an `Into` clause specifying the entity type + - parameter objectID: the `NSManagedObjectID` for the object to be edited + - returns: an editable proxy for the specified `NSManagedObject`. */ public override func edit(into: Into, _ objectID: NSManagedObjectID) -> T? { - CoreStore.assert(!self.isCommitted, "Attempted to update an entity of type <\(T.self)> from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to update an entity of type \(typeName(T)) from an already committed \(typeName(self))." + ) return super.edit(into, objectID) } @@ -112,11 +133,14 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Deletes a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. - :param: object the `NSManagedObject` type to be deleted + - parameter object: the `NSManagedObject` type to be deleted */ public override func delete(object: NSManagedObject?) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self))." + ) super.delete(object) } @@ -124,13 +148,16 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: object1 the `NSManagedObject` to be deleted - :param: object2 another `NSManagedObject` to be deleted - :param: objects other `NSManagedObject`s to be deleted + - parameter object1: the `NSManagedObject` to be deleted + - parameter object2: another `NSManagedObject` to be deleted + - parameter objects: other `NSManagedObject`s to be deleted */ public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entities from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entities from an already committed \(typeName(self))." + ) super.delete([object1, object2] + objects) } @@ -138,11 +165,14 @@ public final class SynchronousDataTransaction: BaseDataTransaction { /** Deletes the specified `NSManagedObject`s. - :param: objects the `NSManagedObject`s to be deleted + - parameter objects: the `NSManagedObject`s to be deleted */ public override func delete(objects: [NSManagedObject?]) { - CoreStore.assert(!self.isCommitted, "Attempted to delete an entities from an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to delete an entities from an already committed \(typeName(self))." + ) super.delete(objects) } @@ -152,7 +182,10 @@ public final class SynchronousDataTransaction: BaseDataTransaction { */ public override func rollback() { - CoreStore.assert(!self.isCommitted, "Attempted to rollback an already committed \(typeName(self)).") + CoreStore.assert( + !self.isCommitted, + "Attempted to rollback an already committed \(typeName(self))." + ) super.rollback() } @@ -165,9 +198,13 @@ public final class SynchronousDataTransaction: BaseDataTransaction { self.transactionQueue.sync { self.closure(transaction: self) + if !self.isCommitted && self.hasChanges { - CoreStore.log(.Warning, message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded.") + CoreStore.log( + .Warning, + message: "The closure for the \(typeName(self)) completed without being committed. All changes made within the transaction were discarded." + ) } } return self.result diff --git a/CoreStore/Setting Up/CoreStore+Setup.swift b/CoreStore/Setting Up/CoreStore+Setup.swift index 82db6dd..41a695d 100644 --- a/CoreStore/Setting Up/CoreStore+Setup.swift +++ b/CoreStore/Setting Up/CoreStore+Setup.swift @@ -35,8 +35,8 @@ public extension CoreStore { /** Adds an in-memory store to the `defaultStack`. - :param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - :returns: a `PersistentStoreResult` indicating success or failure. + - parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil. + - returns: a `PersistentStoreResult` indicating success or failure. */ public static func addInMemoryStore(configuration: String? = nil) -> PersistentStoreResult { @@ -46,11 +46,11 @@ public extension CoreStore { /** Adds to the `defaultStack` an SQLite store from the given SQLite file name. - :param: fileName the local filename for the SQLite persistent store in the "Application Support" directory. A new SQLite file will be created if it does not exist. - :param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - :param: automigrating Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true. - :param: resetStoreOnMigrationFailure Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false - :returns: a `PersistentStoreResult` indicating success or failure. + - parameter fileName: the local filename for the SQLite persistent store in the "Application Support" directory. A new SQLite file will be created if it does not exist. + - parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil. + - parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true. + - parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false + - returns: a `PersistentStoreResult` indicating success or failure. */ public static func addSQLiteStoreAndWait(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { @@ -65,11 +65,11 @@ public extension CoreStore { /** Adds to the `defaultStack` an SQLite store from the given SQLite file URL. - :param: fileURL the local file URL for the SQLite persistent store. A new SQLite file will be created if it does not exist. If not specified, defaults to a file URL pointing to a ".sqlite" file in the "Application Support" directory. - :param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - :param: automigrating Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true. - :param: resetStoreOnMigrationFailure Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false. - :returns: a `PersistentStoreResult` indicating success or failure. + - parameter fileURL: the local file URL for the SQLite persistent store. A new SQLite file will be created if it does not exist. If not specified, defaults to a file URL pointing to a ".sqlite" file in the "Application Support" directory. + - parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil. + - parameter automigrating: Set to true to configure Core Data auto-migration, or false to disable. If not specified, defaults to true. + - parameter resetStoreOnMigrationFailure: Set to true to delete the store on migration failure; or set to false to throw exceptions on failure instead. Typically should only be set to true when debugging, or if the persistent store can be recreated easily. If not specified, defaults to false. + - returns: a `PersistentStoreResult` indicating success or failure. */ public static func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj index 50aef15..9e0c439 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; }; B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; }; B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; }; - B56007011B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B56007001B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel */; }; B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */; }; B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; }; B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.swift */; }; @@ -43,6 +42,7 @@ B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */; }; B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259A1B3EA4890000406B /* OrganismV3.swift */; }; B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */; }; + B5F45A611B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5F45A601B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -108,7 +108,6 @@ B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - B56007001B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = ""; }; B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = ""; }; B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = ""; }; B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = ""; }; @@ -130,6 +129,7 @@ B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationsDemoViewController.swift; sourceTree = ""; }; B5EE259A1B3EA4890000406B /* OrganismV3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV3.swift; sourceTree = ""; }; B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismProtocol.swift; sourceTree = ""; }; + B5F45A601B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -263,7 +263,7 @@ B5EE25861B36E2520000406B /* OrganismV2.swift */, B5EE25841B36E23C0000406B /* OrganismV1.swift */, B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */, - B56007001B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel */, + B5F45A601B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel */, B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */, ); path = "Migrations Demo"; @@ -307,7 +307,8 @@ B54AAD411AF4D26E00848AE0 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "John Rommel Estropia"; TargetAttributes = { B54AAD481AF4D26E00848AE0 = { @@ -385,12 +386,12 @@ B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */, B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */, B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */, - B56007011B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel in Sources */, B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */, B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */, B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */, B54AAD521AF4D26E00848AE0 /* CoreStoreDemo.xcdatamodeld in Sources */, B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */, + B5F45A611B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel in Sources */, B503FAE11AFDC71700F90881 /* Palette.swift in Sources */, B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */, B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */, @@ -460,6 +461,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -475,7 +477,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -513,7 +515,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; @@ -524,14 +526,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/CoreStoreDemo-ftknhsqfpsthfogvisxisgpbbhsj/Build/Products/Debug-iphoneos", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/CoreStoreDemo-bnajhooxbfnxepepdtkvkfplrqyq/Build/Products/Debug-iphoneos", - ); INFOPLIST_FILE = CoreStoreDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStoreDemo; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -540,14 +538,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/CoreStoreDemo-ftknhsqfpsthfogvisxisgpbbhsj/Build/Products/Debug-iphoneos", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/CoreStoreDemo-bnajhooxbfnxepepdtkvkfplrqyq/Build/Products/Debug-iphoneos", - ); INFOPLIST_FILE = CoreStoreDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStoreDemo; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xccheckout b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xccheckout index ca9ddfb..a385032 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xccheckout +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xccheckout @@ -7,7 +7,7 @@ IDESourceControlProjectIdentifier B6855E48-4B19-4321-B1C7-CB2706E12777 IDESourceControlProjectName - CoreStoreDemo + project IDESourceControlProjectOriginsDictionary 4B60F1BCB491FF717C56441AE7783C74F417BE48 @@ -16,7 +16,7 @@ github.com:JohnEstropia/GCDKit.git IDESourceControlProjectPath - CoreStoreDemo/CoreStoreDemo.xcodeproj + CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace IDESourceControlProjectRelativeInstallPathDictionary 4B60F1BCB491FF717C56441AE7783C74F417BE48 diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xcscmblueprint b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xcscmblueprint new file mode 100644 index 0000000..19c5427 --- /dev/null +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace/xcshareddata/CoreStoreDemo.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "4B60F1BCB491FF717C56441AE7783C74F417BE48", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "8B2E522D57154DFA93A06982C36315ECBEA4FA97" : 0, + "4B60F1BCB491FF717C56441AE7783C74F417BE48" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "B6855E48-4B19-4321-B1C7-CB2706E12777", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "8B2E522D57154DFA93A06982C36315ECBEA4FA97" : "CoreStoreLibraries\/GCDKit", + "4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "CoreStoreDemo", + "DVTSourceControlWorkspaceBlueprintVersion" : 203, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CoreStoreDemo\/CoreStoreDemo.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:JohnEstropia\/CoreStore.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "4B60F1BCB491FF717C56441AE7783C74F417BE48" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:JohnEstropia\/GCDKit.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8B2E522D57154DFA93A06982C36315ECBEA4FA97" + } + ] +} \ No newline at end of file diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcschemes/CoreStoreDemo.xcscheme b/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcschemes/CoreStoreDemo.xcscheme index 4ec6eab..c498118 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcschemes/CoreStoreDemo.xcscheme +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/xcuserdata/johnestropia.xcuserdatad/xcschemes/CoreStoreDemo.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard b/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard index 4c778f7..21d95f8 100644 --- a/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard +++ b/CoreStoreDemo/CoreStoreDemo/Base.lproj/Main.storyboard @@ -1,11 +1,41 @@ - + - + + + + + AppleSDGothicNeo-Regular + + + HelveticaNeue-Bold + HelveticaNeue-Bold + HelveticaNeue + HelveticaNeue + + + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + HelveticaNeue-Light + + @@ -52,17 +82,21 @@ + +