migration utilities (beta), swift 2 conversion

This commit is contained in:
John Rommel Estropia
2015-07-07 08:03:46 +09:00
parent bf0eebe057
commit 5b85b0749e
59 changed files with 1319 additions and 733 deletions

View File

@@ -12,6 +12,7 @@
2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; }; 2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; };
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; }; 2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; };
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.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 */; }; B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; };
B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007131B3F6C2800A9A8F9 /* SectionBy.swift */; }; B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007131B3F6C2800A9A8F9 /* SectionBy.swift */; };
B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007151B4018AB00A9A8F9 /* MigrationChain.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; }; 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 = "<group>"; }; 2F291E2619C6D3CF007AF63F /* CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStore.swift; sourceTree = "<group>"; };
B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = "<group>"; }; B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = "<group>"; };
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = "<group>"; };
B56007101B3F6BD500A9A8F9 /* Into.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Into.swift; sourceTree = "<group>"; }; B56007101B3F6BD500A9A8F9 /* Into.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Into.swift; sourceTree = "<group>"; };
B56007131B3F6C2800A9A8F9 /* SectionBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionBy.swift; sourceTree = "<group>"; }; B56007131B3F6C2800A9A8F9 /* SectionBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionBy.swift; sourceTree = "<group>"; };
B56007151B4018AB00A9A8F9 /* MigrationChain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChain.swift; sourceTree = "<group>"; }; B56007151B4018AB00A9A8F9 /* MigrationChain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChain.swift; sourceTree = "<group>"; };
@@ -389,6 +391,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */, B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */,
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */,
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */, B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */, B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */,
B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */, B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */,
@@ -457,7 +460,8 @@
2F03A52719C5C6DA005002A5 /* Project object */ = { 2F03A52719C5C6DA005002A5 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0600; LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "John Rommel Estropia"; ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = { TargetAttributes = {
2F03A52F19C5C6DA005002A5 = { 2F03A52F19C5C6DA005002A5 = {
@@ -564,6 +568,7 @@
B5E84F0F1AFF847B0064E85B /* From.swift in Sources */, B5E84F0F1AFF847B0064E85B /* From.swift in Sources */,
B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */, B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */,
B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */, B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */,
B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */,
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */, B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */,
B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */, B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */,
B5E84F311AFF849C0064E85B /* WeakObject.swift in Sources */, B5E84F311AFF849C0064E85B /* WeakObject.swift in Sources */,
@@ -628,6 +633,7 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
@@ -707,6 +713,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_SWIFT_FLAGS = "-D DEBUG"; OTHER_SWIFT_FLAGS = "-D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -727,6 +734,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_OPTIMIZATION_LEVEL = "-O";
@@ -748,6 +756,7 @@
); );
INFOPLIST_FILE = CoreStoreTests/Info.plist; INFOPLIST_FILE = CoreStoreTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Debug; name = Debug;
@@ -762,6 +771,7 @@
); );
INFOPLIST_FILE = CoreStoreTests/Info.plist; INFOPLIST_FILE = CoreStoreTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Release; name = Release;

View File

@@ -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"
}
]
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0630" LastUpgradeVersion = "0700"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -62,6 +62,8 @@
ReferencedContainer = "container:CoreStore.xcodeproj"> ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
@@ -71,6 +73,7 @@
buildConfiguration = "Debug" buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference

View File

@@ -36,13 +36,16 @@ public extension BaseDataTransaction {
/** /**
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses. 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 - parameter 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. - 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 - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/ */
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? { public func fetchOne<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/ */
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? { public func fetchOne<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/ */
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? { public func fetchAll<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/ */
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? { public func fetchAll<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? { public func fetchCount<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? { public func fetchCount<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/ */
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/ */
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: the number of `NSManagedObject`s deleted - returns: the number of `NSManagedObject`s deleted
*/ */
public func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: DeleteClause...) -> Int? { public func deleteAll<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter 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. - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: the number of `NSManagedObject`s deleted - returns: the number of `NSManagedObject`s deleted
*/ */
public func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? { public func deleteAll<T: NSManagedObject>(from: From<T>, _ 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) 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? { public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ 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) 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? { public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ 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) 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? { public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ 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) 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? { public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ 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) return self.context.queryAttributes(from, selectClause, queryClauses)
} }

View File

@@ -39,7 +39,7 @@ public struct GroupBy: QueryClause {
/** /**
Initializes a `GroupBy` clause with a list of key path strings 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]) { public init(_ keyPaths: [KeyPath]) {
@@ -57,8 +57,8 @@ public struct GroupBy: QueryClause {
/** /**
Initializes a `GroupBy` clause with a list of key path strings Initializes a `GroupBy` clause with a list of key path strings
:param: keyPath a key path string to group results with - parameter keyPath: a key path string to group results with
:param: keyPaths a series of key path strings to group results with - parameter keyPaths: a series of key path strings to group results with
*/ */
public init(_ keyPath: KeyPath, _ keyPaths: KeyPath...) { public init(_ keyPath: KeyPath, _ keyPaths: KeyPath...) {
@@ -74,7 +74,10 @@ public struct GroupBy: QueryClause {
if fetchRequest.propertiesToGroupBy != nil { 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 fetchRequest.propertiesToGroupBy = self.keyPaths

View File

@@ -73,7 +73,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause {
/** /**
Initializes a `OrderBy` clause with a list of sort descriptors 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]) { public init(_ sortDescriptors: [NSSortDescriptor]) {
@@ -91,7 +91,7 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause {
/** /**
Initializes a `OrderBy` clause with a single sort descriptor Initializes a `OrderBy` clause with a single sort descriptor
:param: sortDescriptor a `NSSortDescriptor` - parameter sortDescriptor: a `NSSortDescriptor`
*/ */
public init(_ sortDescriptor: 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 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]) { public init(_ sortKey: [SortKey]) {
self.init( self.init(
sortKey.map { SortKey -> NSSortDescriptor in sortKey.map { sortKey -> NSSortDescriptor in
switch SortKey { switch sortKey {
case .Ascending(let keyPath): case .Ascending(let keyPath):
return NSSortDescriptor(key: keyPath, ascending: true) 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 Initializes a `OrderBy` clause with a series of `SortKey`s
:param: sortKey a single `SortKey` - parameter sortKey: a single `SortKey`
:param: sortKeys a series of `SortKey`s - parameter sortKeys: a series of `SortKey`s
*/ */
public init(_ sortKey: SortKey, _ sortKeys: SortKey...) { public init(_ sortKey: SortKey, _ sortKeys: SortKey...) {
@@ -140,7 +140,10 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause {
if fetchRequest.sortDescriptors != nil { 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 fetchRequest.sortDescriptors = self.sortDescriptors

View File

@@ -83,8 +83,8 @@ public enum SelectTerm: StringLiteralConvertible {
Where("employeeID", isEqualTo: 1111) Where("employeeID", isEqualTo: 1111)
) )
:param: keyPath the attribute name - parameter keyPath: the attribute name
:returns: a `SelectTerm` to a `Select` clause for querying an entity attribute - returns: a `SelectTerm` to a `Select` clause for querying an entity attribute
*/ */
public static func Attribute(keyPath: KeyPath) -> SelectTerm { public static func Attribute(keyPath: KeyPath) -> SelectTerm {
@@ -99,9 +99,9 @@ public enum SelectTerm: StringLiteralConvertible {
Select<Int>(.Average("age")) Select<Int>(.Average("age"))
) )
:param: keyPath the attribute name - parameter 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(<attributeName>)" is used - 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(<attributeName>)" is used
:returns: a `SelectTerm` to a `Select` clause for querying the average value of an attribute - returns: a `SelectTerm` to a `Select` clause for querying the average value of an attribute
*/ */
public static func Average(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm { public static func Average(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
@@ -121,9 +121,9 @@ public enum SelectTerm: StringLiteralConvertible {
Select<Int>(.Count("employeeID")) Select<Int>(.Count("employeeID"))
) )
:param: keyPath the attribute name - parameter 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(<attributeName>)" is used - 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(<attributeName>)" is used
:returns: a `SelectTerm` to a `Select` clause for a count query - returns: a `SelectTerm` to a `Select` clause for a count query
*/ */
public static func Count(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm { public static func Count(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
@@ -143,9 +143,9 @@ public enum SelectTerm: StringLiteralConvertible {
Select<Int>(.Maximum("age")) Select<Int>(.Maximum("age"))
) )
:param: keyPath the attribute name - parameter 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(<attributeName>)" is used - 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(<attributeName>)" is used
:returns: a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute - returns: a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute
*/ */
public static func Maximum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm { public static func Maximum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
@@ -165,9 +165,9 @@ public enum SelectTerm: StringLiteralConvertible {
Select<Int>(.Minimum("age")) Select<Int>(.Minimum("age"))
) )
:param: keyPath the attribute name - parameter 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(<attributeName>)" is used - 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(<attributeName>)" is used
:returns: a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute - returns: a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute
*/ */
public static func Minimum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm { public static func Minimum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
@@ -187,9 +187,9 @@ public enum SelectTerm: StringLiteralConvertible {
Select<Int>(.Sum("age")) Select<Int>(.Sum("age"))
) )
:param: keyPath the attribute name - parameter 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(<attributeName>)" is used - 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(<attributeName>)" is used
:returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
*/ */
public static func Sum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm { public static func Sum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
@@ -267,7 +267,7 @@ Valid return types depend on the query:
- for `queryAttributes(...)` methods: - for `queryAttributes(...)` methods:
- `NSDictionary` - `NSDictionary`
:param: sortDescriptors a series of `NSSortDescriptor`s - parameter sortDescriptors: a series of `NSSortDescriptor`s
*/ */
public struct Select<T: SelectResultType> { public struct Select<T: SelectResultType> {
@@ -281,8 +281,8 @@ public struct Select<T: SelectResultType> {
/** /**
Initializes a `Select` clause with a list of `SelectTerm`s Initializes a `Select` clause with a list of `SelectTerm`s
:param: selectTerm a `SelectTerm` - parameter selectTerm: a `SelectTerm`
:param: selectTerms a series of `SelectTerm`s - parameter selectTerms: a series of `SelectTerm`s
*/ */
public init(_ selectTerm: SelectTerm, _ selectTerms: SelectTerm...) { public init(_ selectTerm: SelectTerm, _ selectTerms: SelectTerm...) {
@@ -296,7 +296,10 @@ public struct Select<T: SelectResultType> {
if fetchRequest.propertiesToFetch != nil { 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 fetchRequest.includesPendingChanges = false
@@ -312,17 +315,20 @@ public struct Select<T: SelectResultType> {
switch term { switch term {
case ._Attribute(let keyPath): case ._Attribute(let keyPath):
if let propertyDescription = propertiesByName[keyPath] as? NSPropertyDescription { if let propertyDescription = propertiesByName[keyPath] {
propertiesToFetch.append(propertyDescription) propertiesToFetch.append(propertyDescription)
} }
else { 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): 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() let expressionDescription = NSExpressionDescription()
expressionDescription.name = alias expressionDescription.name = alias
@@ -343,7 +349,10 @@ public struct Select<T: SelectResultType> {
} }
else { 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 // MARK: - NSDecimalNumber: SelectValueResultType
extension NSDecimalNumber: SelectValueResultType { extension NSDecimalNumber {
public override class var attributeType: NSAttributeType { public override class var attributeType: NSAttributeType {

View File

@@ -49,7 +49,7 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause {
/** /**
Initializes a `Tweak` clause with a closure where the `NSFetchRequest` may be configured. 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) { public init(_ customization: (fetchRequest: NSFetchRequest) -> Void) {

View File

@@ -54,7 +54,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause {
/** /**
Initializes a `Where` clause with an `NSPredicate` 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) { 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 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) { 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 Initializes a `Where` clause with a predicate using the specified string format and arguments
:param: format the format string for the predicate - parameter format: the format string for the predicate
:param: args the arguments for `format` - parameter args: the arguments for `format`
*/ */
public init(_ format: String, _ args: NSObject...) { 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 Initializes a `Where` clause with a predicate using the specified string format and arguments
:param: format the format string for the predicate - parameter format: the format string for the predicate
:param: argumentArray the arguments for `format` - parameter argumentArray: the arguments for `format`
*/ */
public init(_ format: String, argumentArray: [NSObject]?) { 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 Initializes a `Where` clause with a predicate using the specified string format and arguments
:param: format the format string for the predicate - parameter format: the format string for the predicate
:param: argumentArray the arguments for `format` - parameter argumentArray: the arguments for `format`
*/ */
public init(_ keyPath: KeyPath, isEqualTo value: NSObject?) { public init(_ keyPath: KeyPath, isEqualTo value: NSObject?) {
@@ -123,7 +123,10 @@ public struct Where: FetchClause, QueryClause, DeleteClause {
if fetchRequest.predicate != nil { 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 fetchRequest.predicate = self.predicate

View File

@@ -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. 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 - parameter 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. - 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 - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/ */
public static func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? { public static func fetchOne<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/ */
public static func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? { public static func fetchOne<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/ */
public static func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? { public static func fetchAll<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/ */
public static func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? { public static func fetchAll<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public static func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? { public static func fetchCount<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public static func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? { public static func fetchCount<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/ */
public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? { public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/ */
public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? { public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? { public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter 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. - 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 - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/ */
public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? { public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? { public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? { public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? { public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ 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. 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 - parameter from: a `From` clause indicating the entity type
:param: selectClause a `Select<U>` clause indicating the properties to fetch, and with the generic type indicating the return type. - parameter selectClause: a `Select<U>` 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. - 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<U>` parameter. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/ */
public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? { public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@@ -42,27 +42,27 @@ internal func getAssociatedObjectForKey<T: AnyObject>(key: UnsafePointer<Void>,
internal func setAssociatedRetainedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) { internal func setAssociatedRetainedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, 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<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) { internal func setAssociatedCopiedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, 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<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) { internal func setAssociatedAssignedObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
objc_setAssociatedObject(object, key, associatedObject, UInt(OBJC_ASSOCIATION_ASSIGN)) objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_ASSIGN)
} }
internal func setAssociatedWeakObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) { internal func setAssociatedWeakObject<T: AnyObject>(associatedObject: T?, forKey key: UnsafePointer<Void>, inObject object: AnyObject) {
if let associatedObject = associatedObject { 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 { else {
objc_setAssociatedObject(object, key, nil, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) objc_setAssociatedObject(object, key, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
} }
} }

View File

@@ -35,7 +35,7 @@ internal extension NSManagedObject {
internal dynamic class func createInContext(context: NSManagedObjectContext) -> Self { internal dynamic class func createInContext(context: NSManagedObjectContext) -> Self {
return self( return self.init(
entity: context.entityDescriptionForEntityType(self)!, entity: context.entityDescriptionForEntityType(self)!,
insertIntoManagedObjectContext: context insertIntoManagedObjectContext: context
) )
@@ -61,16 +61,19 @@ internal extension NSManagedObject {
private class func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext, objectID: NSManagedObjectID) -> T? { private class func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext, objectID: NSManagedObjectID) -> T? {
var error: NSError? do {
if let existingObject = context.existingObjectWithID(objectID, error: &error) {
let existingObject = try context.existingObjectWithID(objectID)
return (existingObject as! T) return (existingObject as! T)
} }
catch {
CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), CoreStore.handleError(
"Failed to load existing \(typeName(self)) in context.") error as NSError,
return nil; "Failed to load existing \(typeName(self)) in context."
)
return nil
}
} }
private func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext) -> T? { private func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext) -> T? {
@@ -78,29 +81,42 @@ internal extension NSManagedObject {
let objectID = self.objectID let objectID = self.objectID
if objectID.temporaryID { if objectID.temporaryID {
var error: NSError? var objectIDError: NSError?
let didSucceed = withExtendedLifetime(self.managedObjectContext) { 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 { if didSucceed != true {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), objectIDError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed to obtain permanent ID for object.") "Failed to obtain permanent ID for object."
)
return nil return nil
} }
} }
var error: NSError? do {
if let existingObject = context.existingObjectWithID(objectID, error: &error) {
let existingObject = try context.existingObjectWithID(objectID)
return (existingObject as! T) return (existingObject as! T)
} }
catch {
CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), CoreStore.handleError(
"Failed to load existing \(typeName(self)) in context.") error as NSError,
return nil; "Failed to load existing \(typeName(self)) in context."
)
return nil
}
} }
} }

View File

@@ -73,10 +73,7 @@ internal extension NSManagedObjectContext {
internal func setupForCoreStoreWithContextName(contextName: String) { internal func setupForCoreStoreWithContextName(contextName: String) {
if self.respondsToSelector("setName:") { self.name = contextName
self.name = contextName
}
self.observerForWillSaveNotification = NotificationObserver( self.observerForWillSaveNotification = NotificationObserver(
notificationName: NSManagedObjectContextWillSaveNotification, notificationName: NSManagedObjectContextWillSaveNotification,
@@ -91,16 +88,18 @@ internal extension NSManagedObjectContext {
return return
} }
var error: NSError? do {
if context.obtainPermanentIDsForObjects(Array(insertedObjects), error: &error) {
try context.obtainPermanentIDsForObjects(Array(insertedObjects))
return return
} }
catch {
CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), CoreStore.handleError(
"Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s)." error as NSError,
) "Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s)."
)
}
} }
) )
} }

View File

@@ -52,16 +52,24 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [T]? var fetchResults: [T]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { 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 { if fetchResults == nil {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -87,16 +95,24 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [T]? var fetchResults: [T]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { 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 { if fetchResults == nil {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -128,7 +144,8 @@ internal extension NSManagedObjectContext {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), error ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -154,16 +171,24 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [NSManagedObjectID]? var fetchResults: [NSManagedObjectID]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { 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 { if fetchResults == nil {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -189,16 +214,24 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [NSManagedObjectID]? var fetchResults: [NSManagedObjectID]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { 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 { if fetchResults == nil {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -225,26 +258,32 @@ internal extension NSManagedObjectContext {
} }
var numberOfDeletedObjects: Int? var numberOfDeletedObjects: Int?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { self.performBlockAndWait {
autoreleasepool { 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 { for object in fetchResults {
self.deleteObject(object) self.deleteObject(object)
} }
numberOfDeletedObjects = fetchResults.count
}
catch {
fetchError = error as NSError
} }
} }
} }
if numberOfDeletedObjects == nil { if numberOfDeletedObjects == nil {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -271,10 +310,17 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [AnyObject]? var fetchResults: [AnyObject]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { self.performBlockAndWait {
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) do {
fetchResults = try self.executeFetchRequest(fetchRequest)
}
catch {
fetchError = error as NSError
}
} }
if let fetchResults = fetchResults { if let fetchResults = fetchResults {
@@ -287,8 +333,9 @@ internal extension NSManagedObjectContext {
} }
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
@@ -312,10 +359,17 @@ internal extension NSManagedObjectContext {
} }
var fetchResults: [AnyObject]? var fetchResults: [AnyObject]?
var error: NSError? var fetchError: NSError?
self.performBlockAndWait { self.performBlockAndWait {
fetchResults = self.executeFetchRequest(fetchRequest, error: &error) do {
fetchResults = try self.executeFetchRequest(fetchRequest)
}
catch {
fetchError = error as NSError
}
} }
if let fetchResults = fetchResults { if let fetchResults = fetchResults {
@@ -323,8 +377,9 @@ internal extension NSManagedObjectContext {
} }
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), fetchError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed executing fetch request.") "Failed executing fetch request."
)
return nil return nil
} }
} }

View File

@@ -68,44 +68,43 @@ internal extension NSManagedObjectContext {
internal func saveSynchronously() -> SaveResult { internal func saveSynchronously() -> SaveResult {
var result = SaveResult(hasChanges: false) var result = SaveResult(hasChanges: false)
self.performBlockAndWait {
[unowned self] () -> Void in self.performBlockAndWait { [unowned self] () -> Void in
if !self.hasChanges { if !self.hasChanges {
return return
} }
var saveError: NSError? do {
if self.save(&saveError) {
if self.shouldCascadeSavesToParent { try self.save()
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)
} }
else if let error = saveError { catch {
let saveError = error as NSError
CoreStore.handleError( CoreStore.handleError(
error, saveError,
"Failed to save <\(NSManagedObjectContext.self)>.") "Failed to save \(typeName(NSManagedObjectContext))."
result = SaveResult(error) )
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 { else {
result = SaveResult(hasChanges: false) result = SaveResult(hasChanges: true)
} }
} }
@@ -128,43 +127,35 @@ internal extension NSManagedObjectContext {
return return
} }
var saveError: NSError? do {
if self.save(&saveError) {
if self.shouldCascadeSavesToParent { try self.save()
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))
}
}
} }
else if let error = saveError { catch {
let saveError = error as NSError
CoreStore.handleError( CoreStore.handleError(
error, saveError,
"Failed to save <\(NSManagedObjectContext.self)>.") "Failed to save \(typeName(NSManagedObjectContext))."
)
if let completion = completion { if let completion = completion {
GCDQueue.Main.async { 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 { GCDQueue.Main.async {
completion(result: SaveResult(hasChanges: false)) completion(result: SaveResult(hasChanges: true))
} }
} }
} }

View File

@@ -33,25 +33,177 @@ internal extension NSManagedObjectModel {
// MARK: Internal // 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<String>? {
get {
let value: NSSet? = getAssociatedObjectForKey(
&PropertyKeys.modelVersions,
inObject: self
)
return value as? Set<String>
}
set {
setAssociatedCopiedObject(
newValue == nil ? nil : (newValue! as NSSet),
forKey: &PropertyKeys.modelVersions,
inObject: self
)
}
}
func entityNameForClass(entityClass: AnyClass) -> String { func entityNameForClass(entityClass: AnyClass) -> String {
return self.entityNameMapping[NSStringFromClass(entityClass)]! return self.entityNameMapping[NSStringFromClass(entityClass)]!
} }
func configurationsForClass(entityClass: AnyClass) -> Set<String> { 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 // MARK: Private
private var modelVersionFileURL: NSURL? {
internal var entityNameMapping: [String: String] {
get { 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] return mapping as! [String: String]
} }
@@ -75,25 +227,12 @@ internal extension NSManagedObjectModel {
} }
} }
private lazy var entityConfigurationsMapping: [String: Set<String>] = {
[unowned self] in
return self.configurations.reduce([String: Set<String>]()) {
(var mapping, configuration) -> [String: Set<String>] in
return (self.entitiesForConfiguration(configuration) ?? []).reduce(mapping) {
(var mapping, entityDescription) -> [String: Set<String>] in
let className = entityDescription.managedObjectClassName
mapping[className]?.insert(configuration)
return mapping
}
}
}()
private struct PropertyKeys { private struct PropertyKeys {
static var entityNameMapping: Void? static var entityNameMapping: Void?
static var entityConfigurationsMapping: Void?
static var modelVersionFileURL: Void?
static var modelVersions: Void?
static var currentModelVersion: Void?
} }
} }

View File

@@ -36,7 +36,7 @@ internal final class NotificationObserver {
let object: AnyObject? let object: AnyObject?
let observer: NSObjectProtocol 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.notificationName = notificationName
self.object = object self.object = object

View File

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

View File

@@ -60,7 +60,8 @@ public extension CoreStore {
message: message, message: message,
fileName: fileName, fileName: fileName,
lineNumber: lineNumber, lineNumber: lineNumber,
functionName: functionName) functionName: functionName
)
} }
internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) { 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, message: message,
fileName: fileName, fileName: fileName,
lineNumber: lineNumber, 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
)
} }
} }

View File

@@ -56,7 +56,7 @@ public protocol CoreStoreLogger {
:lineNumber: the source line number :lineNumber: the source line number
:functionName: the source function name :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. Handles errors sent by the `CoreStore` framework.
@@ -67,7 +67,7 @@ public protocol CoreStoreLogger {
:lineNumber: the source line number :lineNumber: the source line number
:functionName: the source function name :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. Handles assertions made throughout the `CoreStore` framework.
@@ -79,6 +79,16 @@ public protocol CoreStoreLogger {
:functionName: the source function name :functionName: the source function name
*/ */
func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) 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)>" return "<\(value)>"
} }
internal func typeName(name: String?) -> String {
let typeName = name ?? "unknown"
return "<\(typeName)>"
}

View File

@@ -31,15 +31,15 @@ import Foundation
/** /**
The `DefaultLogger` is a basic implementation of the `CoreStoreLogger` protocol. 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 `log(...)` method calls `print(...)` 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 `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. - The `assert(...)` method calls `assert(...)` on the arguments.
*/ */
public final class DefaultLogger: CoreStoreLogger { public final class DefaultLogger: CoreStoreLogger {
public init() { } 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 #if DEBUG
let levelString: String let levelString: String
@@ -49,14 +49,14 @@ public final class DefaultLogger: CoreStoreLogger {
case .Warning: levelString = "Warning" case .Warning: levelString = "Warning"
case .Fatal: levelString = "Fatal" 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 #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 #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 #endif
} }
@@ -66,4 +66,9 @@ public final class DefaultLogger: CoreStoreLogger {
Swift.assert(condition, message, file: fileName, line: numericCast(lineNumber)) Swift.assert(condition, message, file: fileName, line: numericCast(lineNumber))
#endif #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")
}
} }

View File

@@ -42,7 +42,11 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
public func nextVersionFrom(version: String) -> String? { 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] self.leafVersions = [value]
} }
// MARK: ExtendedGraphemeClusterLiteralConvertible // MARK: ExtendedGraphemeClusterLiteralConvertible
public init(extendedGraphemeClusterLiteral value: String) { public init(extendedGraphemeClusterLiteral value: String) {
@@ -126,8 +131,8 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
} }
self.versionTree = versionTree self.versionTree = versionTree
self.rootVersions = Set(flatMap([elements.first]) { $0 == nil ? [] : [$0!] }) self.rootVersions = Set([elements.first].flatMap { $0 == nil ? [] : [$0!] })
self.leafVersions = Set(flatMap([elements.last]) { $0 == nil ? [] : [$0!] }) self.leafVersions = Set([elements.last].flatMap { $0 == nil ? [] : [$0!] })
} }

View File

@@ -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`. 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 - parameter object: the `NSManagedObject` to observe changes from
:returns: a `ObjectMonitor` that monitors changes to `object` - returns: a `ObjectMonitor` that monitors changes to `object`
*/ */
public static func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> { public static func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> {
@@ -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. 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 - parameter 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. - 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 - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ListMonitor<T> { public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ListMonitor<T> {
@@ -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. 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 - parameter 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. - 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 - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ListMonitor<T> { public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ListMonitor<T> {
@@ -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. 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 - parameter 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. - parameter 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. - 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 - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> { public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
@@ -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. 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 - parameter 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. - parameter 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. - 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 - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> { public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {

View File

@@ -74,32 +74,32 @@ public final class ListMonitor<T: NSManagedObject> {
/** /**
Accesses the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `addObserver(_:)`. 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 { public subscript(index: Int) -> T {
return self.fetchedResultsController.objectAtIndexPath(NSIndexPath(forItem: index, inSection: 0)) as! T return self[0, index]
}
/**
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
} }
/** /**
Accesses the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`. 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. - parameter 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 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 { 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<T: NSManagedObject> {
/** /**
Returns the number of objects in the specified section 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 { 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 Returns the `NSFetchedResultsSectionInfo` for the specified section
:param: section the section index - parameter section: the section index
*/ */
public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo { 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<T: NSManagedObject> {
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. 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<U: ListObserver where U.EntityType == T>(observer: U) { public func addObserver<U: ListObserver where U.EntityType == T>(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) self.removeObserver(observer)
@@ -182,11 +185,14 @@ public final class ListMonitor<T: NSManagedObject> {
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. 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<U: ListObjectObserver where U.EntityType == T>(observer: U) { public func addObserver<U: ListObjectObserver where U.EntityType == T>(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) self.removeObserver(observer)
@@ -291,11 +297,14 @@ public final class ListMonitor<T: NSManagedObject> {
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them. 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<U: ListSectionObserver where U.EntityType == T>(observer: U) { public func addObserver<U: ListSectionObserver where U.EntityType == T>(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) self.removeObserver(observer)
@@ -429,11 +438,14 @@ public final class ListMonitor<T: NSManagedObject> {
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. 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<U: ListObserver where U.EntityType == T>(observer: U) { public func removeObserver<U: ListObserver where U.EntityType == T>(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 let nilValue: AnyObject? = nil
setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeList, inObject: observer) setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeList, inObject: observer)
@@ -492,12 +504,16 @@ public final class ListMonitor<T: NSManagedObject> {
fetchedResultsControllerDelegate.handler = self fetchedResultsControllerDelegate.handler = self
fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
var error: NSError? do {
if !fetchedResultsController.performFetch(&error) {
try fetchedResultsController.performFetch()
}
catch {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), error as NSError,
"Failed to perform fetch on <\(NSFetchedResultsController.self)>.") "Failed to perform fetch on \(typeName(NSFetchedResultsController))."
)
} }
} }
@@ -705,31 +721,31 @@ private protocol FetchedResultsControllerHandler: class {
// MARK: - FetchedResultsControllerDelegate // MARK: - FetchedResultsControllerDelegate
private final class FetchedResultsControllerDelegate: NSFetchedResultsControllerDelegate { private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
// MARK: NSFetchedResultsControllerDelegate // MARK: NSFetchedResultsControllerDelegate
@objc func controllerWillChangeContent(controller: NSFetchedResultsController) { @objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.handler?.controllerWillChangeContent(controller) self.handler?.controllerWillChangeContent(controller)
} }
@objc func controllerDidChangeContent(controller: NSFetchedResultsController) { @objc dynamic func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.handler?.controllerDidChangeContent(controller) 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) 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) 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) return self.handler?.controller(controller, sectionIndexTitleForSectionName: sectionName)
} }

View File

@@ -48,14 +48,14 @@ public protocol ListObserver: class {
/** /**
Handles processing just before a change to the observed list occurs 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<EntityType>) func listMonitorWillChange(monitor: ListMonitor<EntityType>)
/** /**
Handles processing right after a change to the observed list occurs 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<EntityType>) func listMonitorDidChange(monitor: ListMonitor<EntityType>)
} }
@@ -77,37 +77,37 @@ public protocol ListObjectObserver: ListObserver {
/** /**
Notifies that an object was inserted to the specified `NSIndexPath` in the list Notifies that an object was inserted to the specified `NSIndexPath` in the list
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: object the entity type for the inserted object - parameter object: the entity type for the inserted object
:param: indexPath the new `NSIndexPath` for the inserted object - parameter indexPath: the new `NSIndexPath` for the inserted object
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath) func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath)
/** /**
Notifies that an object was deleted from the specified `NSIndexPath` in the list Notifies that an object was deleted from the specified `NSIndexPath` in the list
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: object the entity type for the deleted object - parameter object: the entity type for the deleted object
:param: indexPath the `NSIndexPath` for the deleted object - parameter indexPath: the `NSIndexPath` for the deleted object
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath) func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath)
/** /**
Notifies that an object at the specified `NSIndexPath` was updated Notifies that an object at the specified `NSIndexPath` was updated
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: object the entity type for the updated object - parameter object: the entity type for the updated object
:param: indexPath the `NSIndexPath` for the updated object - parameter indexPath: the `NSIndexPath` for the updated object
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath) func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath)
/** /**
Notifies that an object's index changed Notifies that an object's index changed
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: object the entity type for the moved object - parameter object: the entity type for the moved object
:param: fromIndexPath the previous `NSIndexPath` for the moved object - parameter fromIndexPath: the previous `NSIndexPath` for the moved object
:param: toIndexPath the new `NSIndexPath` for the moved object - parameter toIndexPath: the new `NSIndexPath` for the moved object
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) func listMonitor(monitor: ListMonitor<EntityType>, 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 Notifies that a section was inserted at the specified index
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the inserted section - parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the inserted section
:param: sectionIndex the new section index for the new section - parameter sectionIndex: the new section index for the new section
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/** /**
Notifies that a section was inserted at the specified index Notifies that a section was inserted at the specified index
:param: monitor the `ListMonitor` monitoring the list being observed - parameter monitor: the `ListMonitor` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the deleted section - parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the deleted section
:param: sectionIndex the previous section index for the deleted section - parameter sectionIndex: the previous section index for the deleted section
*/ */
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
} }

View File

@@ -83,11 +83,14 @@ public final class ObjectMonitor<T: NSManagedObject> {
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ObjectMonitor` unregisters previous notifications to the observer before re-registering them. 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<U: ObjectObserver where U.EntityType == T>(observer: U) { public func addObserver<U: ObjectObserver where U.EntityType == T>(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) self.removeObserver(observer)
@@ -95,9 +98,9 @@ public final class ObjectMonitor<T: NSManagedObject> {
&NotificationKey.willChangeObject, &NotificationKey.willChangeObject,
name: ObjectMonitorWillChangeObjectNotification, name: ObjectMonitorWillChangeObjectNotification,
toObserver: observer, 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) observer.objectMonitor(monitor, willUpdateObject: object)
} }
@@ -107,9 +110,9 @@ public final class ObjectMonitor<T: NSManagedObject> {
&NotificationKey.didDeleteObject, &NotificationKey.didDeleteObject,
name: ObjectMonitorDidDeleteObjectNotification, name: ObjectMonitorDidDeleteObjectNotification,
toObserver: observer, 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) observer.objectMonitor(monitor, didDeleteObject: object)
} }
@@ -124,15 +127,15 @@ public final class ObjectMonitor<T: NSManagedObject> {
if let strongSelf = self, let observer = observer { if let strongSelf = self, let observer = observer {
let previousCommitedAttributes = strongSelf.lastCommittedAttributes let previousCommitedAttributes = strongSelf.lastCommittedAttributes
let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [NSString: NSObject] let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
var changedKeys = Set<String>() let changedKeys = currentCommitedAttributes.keys.reduce(Set<String>()) { (var changedKeys, key) -> Set<String> in
for key in currentCommitedAttributes.keys {
if previousCommitedAttributes[key] != currentCommitedAttributes[key] { if previousCommitedAttributes[key] != currentCommitedAttributes[key] {
changedKeys.insert(key as String) changedKeys.insert(key)
} }
return changedKeys
} }
strongSelf.lastCommittedAttributes = currentCommitedAttributes strongSelf.lastCommittedAttributes = currentCommitedAttributes
@@ -151,11 +154,14 @@ public final class ObjectMonitor<T: NSManagedObject> {
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. 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<U: ObjectObserver where U.EntityType == T>(observer: U) { public func removeObserver<U: ObjectObserver where U.EntityType == T>(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 let nilValue: AnyObject? = nil
setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeObject, inObject: observer) setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeObject, inObject: observer)
@@ -197,15 +203,20 @@ public final class ObjectMonitor<T: NSManagedObject> {
fetchedResultsControllerDelegate.handler = self fetchedResultsControllerDelegate.handler = self
fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
var error: NSError?
if !fetchedResultsController.performFetch(&error) { do {
try fetchedResultsController.performFetch()
}
catch {
CoreStore.handleError( CoreStore.handleError(
error ?? NSError(coreStoreErrorCode: .UnknownError), error as NSError,
"Failed to perform fetch on <\(NSFetchedResultsController.self)>.") "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<T: NSManagedObject> {
private let originalObjectID: NSManagedObjectID private let originalObjectID: NSManagedObjectID
private let fetchedResultsController: NSFetchedResultsController private let fetchedResultsController: NSFetchedResultsController
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
private var lastCommittedAttributes = [NSString: NSObject]() private var lastCommittedAttributes = [String: NSObject]()
private weak var parentStack: DataStack? private weak var parentStack: DataStack?
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor<T>) -> Void) { private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor<T>) -> Void) {
@@ -313,16 +324,16 @@ private protocol FetchedResultsControllerHandler: class {
// MARK: - FetchedResultsControllerDelegate // MARK: - FetchedResultsControllerDelegate
private final class FetchedResultsControllerDelegate: NSFetchedResultsControllerDelegate { private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
// MARK: NSFetchedResultsControllerDelegate // MARK: NSFetchedResultsControllerDelegate
@objc func controllerWillChangeContent(controller: NSFetchedResultsController) { @objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.handler?.controllerWillChangeContent(controller) 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) self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath)
} }

View File

@@ -45,25 +45,25 @@ public protocol ObjectObserver: class {
/** /**
Handles processing just before a change to the observed `object` occurs Handles processing just before a change to the observed `object` occurs
:param: monitor the `ObjectMonitor` monitoring the object being observed - parameter monitor: the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed - parameter object: the `NSManagedObject` instance being observed
*/ */
func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType) func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType)
/** /**
Handles processing right after a change to the observed `object` occurs Handles processing right after a change to the observed `object` occurs
:param: monitor the `ObjectMonitor` monitoring the object being observed - parameter monitor: the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed - parameter 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 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<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>) func objectMonitor(monitor: ObjectMonitor<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>)
/** /**
Handles processing right after `object` is deleted Handles processing right after `object` is deleted
:param: monitor the `ObjectMonitor` monitoring the object being observed - parameter monitor: the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed - parameter object: the `NSManagedObject` instance being observed
*/ */
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType) func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType)
} }

View File

@@ -45,7 +45,7 @@ public struct SectionBy {
/** /**
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections 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) { 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 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 - parameter 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 sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
*/ */
public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: (sectionName: String?) -> String?) { public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: (sectionName: String?) -> String?) {

View File

@@ -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. 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) { public func commit(completion: (result: SaveResult) -> Void) {
CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") CoreStore.assert(
CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") 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.isCommitted = true
let semaphore = GCDSemaphore(0) let semaphore = GCDSemaphore(0)
@@ -63,8 +69,14 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
*/ */
public func commit() { public func commit() {
CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") CoreStore.assert(
CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") 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.isCommitted = true
self.result = self.context.saveSynchronously() 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. 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`. - 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 - 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? { 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(
CoreStore.assert(!self.isCommitted, "Attempted to begin a child transaction from an already committed \(typeName(self)).") 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( return SynchronousDataTransaction(
mainContext: self.context, mainContext: self.context,
@@ -93,12 +111,15 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
/** /**
Creates a new `NSManagedObject` with the specified entity type. Creates a new `NSManagedObject` with the specified entity type.
:param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - 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. - returns: a new `NSManagedObject` instance of the specified entity type.
*/ */
public override func create<T: NSManagedObject>(into: Into<T>) -> T { public override func create<T: NSManagedObject>(into: Into<T>) -> 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) 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. 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 - parameter object: the `NSManagedObject` type to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public override func edit<T: NSManagedObject>(object: T?) -> T? { public override func edit<T: NSManagedObject>(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) 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. 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 - parameter into: an `Into` clause specifying the entity type
:param: objectID the `NSManagedObjectID` for the object to be edited - parameter objectID: the `NSManagedObjectID` for the object to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? { public override func edit<T: NSManagedObject>(into: Into<T>, _ 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) 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. 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?) { 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) super.delete(object)
} }
@@ -145,13 +175,16 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. Deletes the specified `NSManagedObject`s.
:param: object1 the `NSManagedObject` type to be deleted - parameter object1: the `NSManagedObject` type to be deleted
:param: object2 another `NSManagedObject` type to be deleted - parameter object2: another `NSManagedObject` type to be deleted
:param: objects other `NSManagedObject`s type to be deleted - parameter objects: other `NSManagedObject`s type to be deleted
*/ */
public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { 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) super.delete([object1, object2] + objects)
} }
@@ -159,11 +192,14 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. 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?]) { 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) super.delete(objects)
} }
@@ -173,7 +209,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
*/ */
public override func rollback() { 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() super.rollback()
} }
@@ -195,7 +234,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
self.closure(transaction: self) self.closure(transaction: self)
if !self.isCommitted && self.hasChanges { 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.transactionQueue.sync {
self.closure(transaction: self) self.closure(transaction: self)
if !self.isCommitted && self.hasChanges { 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 return self.result

View File

@@ -48,62 +48,68 @@ public /*abstract*/ class BaseDataTransaction {
/** /**
Creates a new `NSManagedObject` with the specified entity type. Creates a new `NSManagedObject` with the specified entity type.
:param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - 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. - returns: a new `NSManagedObject` instance of the specified entity type.
*/ */
public func create<T: NSManagedObject>(into: Into<T>) -> T { public func create<T: NSManagedObject>(into: Into<T>) -> 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 context = self.context
let entityClass = (into.entityClass as! NSManagedObject.Type) let entityClass = (into.entityClass as! NSManagedObject.Type)
let object = entityClass.createInContext(context) as! T
if into.inferStoreIfPossible { if into.inferStoreIfPossible {
switch context.parentStack!.persistentStoreForEntityClass(entityClass, configuration: nil, inferStoreIfPossible: true) { 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) context.assignObject(object, toPersistentStore: persistentStore)
return object
case (.None, true): 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: 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 { else {
switch context.parentStack!.persistentStoreForEntityClass(entityClass, configuration: into.configuration, inferStoreIfPossible: false) { 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) context.assignObject(object, toPersistentStore: persistentStore)
return object
default: default:
if let configuration = into.configuration { 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 { 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`. Returns an editable proxy of a specified `NSManagedObject`.
:param: object the `NSManagedObject` type to be edited - parameter object: the `NSManagedObject` type to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public func edit<T: NSManagedObject>(object: T?) -> T? { public func edit<T: NSManagedObject>(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) return object?.inContext(self.context)
} }
@@ -111,14 +117,21 @@ public /*abstract*/ class BaseDataTransaction {
/** /**
Returns an editable proxy of the object with the specified `NSManagedObjectID`. Returns an editable proxy of the object with the specified `NSManagedObjectID`.
:param: into an `Into` clause specifying the entity type - parameter into: an `Into` clause specifying the entity type
:param: objectID the `NSManagedObjectID` for the object to be edited - parameter objectID: the `NSManagedObjectID` for the object to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? { public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to update an entity of type <\(T.self)> outside its designated queue.") CoreStore.assert(
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`.") 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 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`. Deletes a specified `NSManagedObject`.
:param: object the `NSManagedObject` to be deleted - parameter object: the `NSManagedObject` to be deleted
*/ */
public func delete(object: NSManagedObject?) { 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() object?.inContext(self.context)?.deleteFromContext()
} }
@@ -138,9 +154,9 @@ public /*abstract*/ class BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. Deletes the specified `NSManagedObject`s.
:param: object1 the `NSManagedObject` to be deleted - parameter object1: the `NSManagedObject` to be deleted
:param: object2 another `NSManagedObject` to be deleted - parameter object2: another `NSManagedObject` to be deleted
:param: objects other `NSManagedObject`s to be deleted - parameter objects: other `NSManagedObject`s to be deleted
*/ */
public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
@@ -150,11 +166,14 @@ public /*abstract*/ class BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. 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?]) { 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 let context = self.context
for object in objects { for object in objects {
@@ -170,7 +189,10 @@ public /*abstract*/ class BaseDataTransaction {
*/ */
public func rollback() { 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() self.context.reset()
} }

View File

@@ -35,7 +35,7 @@ public extension CoreStore {
/** /**
Using the `defaultStack`, begins a transaction asynchronously where `NSManagedObject` creates, updates, and deletes can be made. 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) { 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. 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`.
:returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously - 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? { 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. 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 { public static func beginDetached() -> DetachedDataTransaction {

View File

@@ -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. 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) { 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 self.context.saveAsynchronouslyWithCompletion { (result) -> Void in

View File

@@ -68,7 +68,7 @@ public struct Into<T: NSManagedObject> {
let person = transaction.create(Into(MyPersonEntity)) 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) { public init(_ entity: T.Type) {
@@ -80,7 +80,7 @@ public struct Into<T: NSManagedObject> {
/** /**
Initializes an `Into` clause with the specified entity class. 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) { public init(_ entityClass: AnyClass) {
@@ -95,7 +95,7 @@ public struct Into<T: NSManagedObject> {
let person = transaction.create(Into<MyPersonEntity>("Configuration1")) let person = transaction.create(Into<MyPersonEntity>("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?) { public init(_ configuration: String?) {
@@ -110,8 +110,8 @@ public struct Into<T: NSManagedObject> {
let person = transaction.create(Into(MyPersonEntity.self, "Configuration1")) let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
:param: entity the `NSManagedObject` type to be created - parameter 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 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?) { public init(_ entity: T.Type, _ configuration: String?) {
@@ -126,8 +126,8 @@ public struct Into<T: NSManagedObject> {
let person = transaction.create(Into(MyPersonEntity.self, "Configuration1")) let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
:param: entityClass the `NSManagedObject` class type to be created - parameter 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 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?) { public init(_ entityClass: AnyClass, _ configuration: String?) {

View File

@@ -91,9 +91,7 @@ public enum SaveResult {
internal init(_ errorCode: CoreStoreErrorCode, userInfo: [NSObject: AnyObject]?) { internal init(_ errorCode: CoreStoreErrorCode, userInfo: [NSObject: AnyObject]?) {
self.init(NSError( self.init(NSError(coreStoreErrorCode: errorCode, userInfo: userInfo))
coreStoreErrorCode: errorCode,
userInfo: userInfo))
} }
} }

View File

@@ -42,8 +42,14 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
*/ */
public func commit() { public func commit() {
CoreStore.assert(self.transactionQueue.isCurrentExecutionContext(), "Attempted to commit a \(typeName(self)) outside its designated queue.") CoreStore.assert(
CoreStore.assert(!self.isCommitted, "Attempted to commit a \(typeName(self)) more than once.") 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.isCommitted = true
self.result = self.context.saveSynchronously() 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. 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`. - 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 - 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? { 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(
CoreStore.assert(!self.isCommitted, "Attempted to begin a child transaction from an already committed \(typeName(self)).") 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( return SynchronousDataTransaction(
mainContext: self.context, mainContext: self.context,
@@ -72,12 +84,15 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
/** /**
Creates a new `NSManagedObject` with the specified entity type. Creates a new `NSManagedObject` with the specified entity type.
:param: into the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration - 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. - returns: a new `NSManagedObject` instance of the specified entity type.
*/ */
public override func create<T: NSManagedObject>(into: Into<T>) -> T { public override func create<T: NSManagedObject>(into: Into<T>) -> 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) 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. 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 - parameter object: the `NSManagedObject` type to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public override func edit<T: NSManagedObject>(object: T?) -> T? { public override func edit<T: NSManagedObject>(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) 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. 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 - parameter into: an `Into` clause specifying the entity type
:param: objectID the `NSManagedObjectID` for the object to be edited - parameter objectID: the `NSManagedObjectID` for the object to be edited
:returns: an editable proxy for the specified `NSManagedObject`. - returns: an editable proxy for the specified `NSManagedObject`.
*/ */
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? { public override func edit<T: NSManagedObject>(into: Into<T>, _ 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) 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. 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?) { 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) super.delete(object)
} }
@@ -124,13 +148,16 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. Deletes the specified `NSManagedObject`s.
:param: object1 the `NSManagedObject` to be deleted - parameter object1: the `NSManagedObject` to be deleted
:param: object2 another `NSManagedObject` to be deleted - parameter object2: another `NSManagedObject` to be deleted
:param: objects other `NSManagedObject`s to be deleted - parameter objects: other `NSManagedObject`s to be deleted
*/ */
public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { 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) super.delete([object1, object2] + objects)
} }
@@ -138,11 +165,14 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
/** /**
Deletes the specified `NSManagedObject`s. 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?]) { 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) super.delete(objects)
} }
@@ -152,7 +182,10 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
*/ */
public override func rollback() { 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() super.rollback()
} }
@@ -165,9 +198,13 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
self.transactionQueue.sync { self.transactionQueue.sync {
self.closure(transaction: self) self.closure(transaction: self)
if !self.isCommitted && self.hasChanges { 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 return self.result

View File

@@ -35,8 +35,8 @@ public extension CoreStore {
/** /**
Adds an in-memory store to the `defaultStack`. Adds an in-memory store to the `defaultStack`.
:param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - parameter configuration: an optional configuration name from the model file. If not specified, defaults to nil.
:returns: a `PersistentStoreResult` indicating success or failure. - returns: a `PersistentStoreResult` indicating success or failure.
*/ */
public static func addInMemoryStore(configuration: String? = nil) -> PersistentStoreResult { 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. 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. - 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.
:param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - parameter 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. - parameter 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 - 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. - returns: a `PersistentStoreResult` indicating success or failure.
*/ */
public static func addSQLiteStoreAndWait(fileName: String, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { 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. 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 "<Application name>.sqlite" file in the "Application Support" directory. - 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 "<Application name>.sqlite" file in the "Application Support" directory.
:param: configuration an optional configuration name from the model file. If not specified, defaults to nil. - parameter 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. - parameter 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. - 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. - returns: a `PersistentStoreResult` indicating success or failure.
*/ */
public static func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult { public static func addSQLiteStoreAndWait(fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, automigrating: Bool = true, resetStoreOnMigrationFailure: Bool = false) -> PersistentStoreResult {

View File

@@ -21,7 +21,6 @@
B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; }; B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; };
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; }; B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; };
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; }; 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 */; }; B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */; };
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; }; B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; };
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.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 */; }; B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */; };
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259A1B3EA4890000406B /* OrganismV3.swift */; }; B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259A1B3EA4890000406B /* OrganismV3.swift */; };
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259D1B3EC1B20000406B /* OrganismProtocol.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 */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -108,7 +108,6 @@
B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; }; B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
B56007001B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = "<group>"; };
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = "<group>"; }; B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = "<group>"; };
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = "<group>"; }; B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = "<group>"; };
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = "<group>"; }; B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = "<group>"; };
@@ -130,6 +129,7 @@
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationsDemoViewController.swift; sourceTree = "<group>"; }; B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationsDemoViewController.swift; sourceTree = "<group>"; };
B5EE259A1B3EA4890000406B /* OrganismV3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV3.swift; sourceTree = "<group>"; }; B5EE259A1B3EA4890000406B /* OrganismV3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV3.swift; sourceTree = "<group>"; };
B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismProtocol.swift; sourceTree = "<group>"; }; B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismProtocol.swift; sourceTree = "<group>"; };
B5F45A601B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -263,7 +263,7 @@
B5EE25861B36E2520000406B /* OrganismV2.swift */, B5EE25861B36E2520000406B /* OrganismV2.swift */,
B5EE25841B36E23C0000406B /* OrganismV1.swift */, B5EE25841B36E23C0000406B /* OrganismV1.swift */,
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */, B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */,
B56007001B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel */, B5F45A601B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel */,
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */, B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */,
); );
path = "Migrations Demo"; path = "Migrations Demo";
@@ -307,7 +307,8 @@
B54AAD411AF4D26E00848AE0 /* Project object */ = { B54AAD411AF4D26E00848AE0 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0630; LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "John Rommel Estropia"; ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = { TargetAttributes = {
B54AAD481AF4D26E00848AE0 = { B54AAD481AF4D26E00848AE0 = {
@@ -385,12 +386,12 @@
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */, B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */,
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */, B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */,
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */, B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */,
B56007011B3EC87400A9A8F9 /* OrganismV2ToV3.xcmappingmodel in Sources */,
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */, B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */,
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */, B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */,
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */, B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */,
B54AAD521AF4D26E00848AE0 /* CoreStoreDemo.xcdatamodeld in Sources */, B54AAD521AF4D26E00848AE0 /* CoreStoreDemo.xcdatamodeld in Sources */,
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */, B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */,
B5F45A611B4AE5A700831F2F /* OrganismV2ToV3.xcmappingmodel in Sources */,
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */, B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */, B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */, B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
@@ -460,6 +461,7 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
@@ -475,7 +477,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -513,7 +515,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
@@ -524,14 +526,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 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; INFOPLIST_FILE = CoreStoreDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStoreDemo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Debug; name = Debug;
@@ -540,14 +538,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 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; INFOPLIST_FILE = CoreStoreDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStoreDemo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Release; name = Release;

View File

@@ -7,7 +7,7 @@
<key>IDESourceControlProjectIdentifier</key> <key>IDESourceControlProjectIdentifier</key>
<string>B6855E48-4B19-4321-B1C7-CB2706E12777</string> <string>B6855E48-4B19-4321-B1C7-CB2706E12777</string>
<key>IDESourceControlProjectName</key> <key>IDESourceControlProjectName</key>
<string>CoreStoreDemo</string> <string>project</string>
<key>IDESourceControlProjectOriginsDictionary</key> <key>IDESourceControlProjectOriginsDictionary</key>
<dict> <dict>
<key>4B60F1BCB491FF717C56441AE7783C74F417BE48</key> <key>4B60F1BCB491FF717C56441AE7783C74F417BE48</key>
@@ -16,7 +16,7 @@
<string>github.com:JohnEstropia/GCDKit.git</string> <string>github.com:JohnEstropia/GCDKit.git</string>
</dict> </dict>
<key>IDESourceControlProjectPath</key> <key>IDESourceControlProjectPath</key>
<string>CoreStoreDemo/CoreStoreDemo.xcodeproj</string> <string>CoreStoreDemo/CoreStoreDemo.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key> <key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict> <dict>
<key>4B60F1BCB491FF717C56441AE7783C74F417BE48</key> <key>4B60F1BCB491FF717C56441AE7783C74F417BE48</key>

View File

@@ -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"
}
]
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0630" LastUpgradeVersion = "0700"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -38,6 +38,8 @@
ReferencedContainer = "container:CoreStoreDemo.xcodeproj"> ReferencedContainer = "container:CoreStoreDemo.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
@@ -47,6 +49,7 @@
buildConfiguration = "Debug" buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">

View File

@@ -1,11 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ni8-QF-XHB"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8121.20" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ni8-QF-XHB">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.16"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/> <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/> <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies> </dependencies>
<customFonts key="customFonts">
<mutableArray key="AppleSDGothicNeo.ttc">
<string>AppleSDGothicNeo-Regular</string>
</mutableArray>
<mutableArray key="HelveticaNeue.ttc">
<string>HelveticaNeue-Bold</string>
<string>HelveticaNeue-Bold</string>
<string>HelveticaNeue</string>
<string>HelveticaNeue</string>
</mutableArray>
<mutableArray key="HelveticaNeueLights.ttc">
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
<string>HelveticaNeue-Light</string>
</mutableArray>
</customFonts>
<scenes> <scenes>
<!--SNS Accounts--> <!--SNS Accounts-->
<scene sceneID="3If-81-mNf"> <scene sceneID="3If-81-mNf">
@@ -52,17 +82,21 @@
</view> </view>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="8b8-lM-Krq" detailTextLabel="hR1-Zb-BOk" style="IBUITableViewCellStyleValue1" id="dMt-nx-EO5"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="8b8-lM-Krq" detailTextLabel="hR1-Zb-BOk" style="IBUITableViewCellStyleValue1" id="dMt-nx-EO5">
<rect key="frame" x="0.0" y="236" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dMt-nx-EO5" id="gdK-VV-zNb"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dMt-nx-EO5" id="gdK-VV-zNb">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8b8-lM-Krq">
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hR1-Zb-BOk">
<rect key="frame" x="533" y="13" width="52" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
@@ -95,7 +129,8 @@
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="KpQ-h6-kAe"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="KpQ-h6-kAe">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/> <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<view key="tableHeaderView" contentMode="scaleToFill" id="5Hd-jr-1nW"> <view key="tableHeaderView" contentMode="scaleToFill" id="5Hd-jr-1nW">
<rect key="frame" x="0.0" y="64" width="600" height="259"/> <rect key="frame" x="0.0" y="64" width="600" height="259"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@@ -130,17 +165,21 @@
</view> </view>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="VMh-dq-EWk" detailTextLabel="HIj-ej-FpM" style="IBUITableViewCellStyleValue1" id="hoX-F9-vzZ"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="VMh-dq-EWk" detailTextLabel="HIj-ej-FpM" style="IBUITableViewCellStyleValue1" id="hoX-F9-vzZ">
<rect key="frame" x="0.0" y="345" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hoX-F9-vzZ" id="9ru-7C-dsE"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hoX-F9-vzZ" id="9ru-7C-dsE">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VMh-dq-EWk"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VMh-dq-EWk">
<rect key="frame" x="15" y="13" width="28.5" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HIj-ej-FpM"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HIj-ej-FpM">
<rect key="frame" x="546.5" y="13" width="38.5" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="16"/>
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/>
@@ -185,17 +224,21 @@
<tableViewSection id="wIP-Hn-YfF"> <tableViewSection id="wIP-Hn-YfF">
<cells> <cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Q3n-Df-v1t" detailTextLabel="Hbn-cf-Y7m" style="IBUITableViewCellStyleSubtitle" id="AXm-KE-45G"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Q3n-Df-v1t" detailTextLabel="Hbn-cf-Y7m" style="IBUITableViewCellStyleSubtitle" id="AXm-KE-45G">
<rect key="frame" x="0.0" y="99" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AXm-KE-45G" id="9te-Wx-hkf"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AXm-KE-45G" id="9te-Wx-hkf">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accounts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q3n-Df-v1t">
<rect key="frame" x="15" y="6" width="82" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901960784313" green="0.24313725490196078" blue="0.31372549019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Setting up multiple persistent store configurations" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hbn-cf-Y7m"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Setting up multiple persistent store configurations" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hbn-cf-Y7m">
<rect key="frame" x="15" y="30" width="264" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -208,17 +251,21 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="vpt-cT-gMo" detailTextLabel="ou9-TZ-8bf" style="IBUITableViewCellStyleSubtitle" id="fsb-zw-8Ii"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="vpt-cT-gMo" detailTextLabel="ou9-TZ-8bf" style="IBUITableViewCellStyleSubtitle" id="fsb-zw-8Ii">
<rect key="frame" x="0.0" y="149" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fsb-zw-8Ii" id="Upm-AO-Fw3"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fsb-zw-8Ii" id="Upm-AO-Fw3">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Colors" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vpt-cT-gMo">
<rect key="frame" x="15" y="6" width="56" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Observing list changes and single object changes" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ou9-TZ-8bf"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Observing list changes and single object changes" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ou9-TZ-8bf">
<rect key="frame" x="15" y="30" width="261.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -231,17 +278,21 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="UbU-Kd-yrY" detailTextLabel="uP1-Jc-o9v" style="IBUITableViewCellStyleSubtitle" id="ekW-PJ-mbo"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="UbU-Kd-yrY" detailTextLabel="uP1-Jc-o9v" style="IBUITableViewCellStyleSubtitle" id="ekW-PJ-mbo">
<rect key="frame" x="0.0" y="199" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekW-PJ-mbo" id="CYq-mg-PVS"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekW-PJ-mbo" id="CYq-mg-PVS">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Placemarks" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UbU-Kd-yrY">
<rect key="frame" x="15" y="6" width="100.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Making changes with transactions" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uP1-Jc-o9v"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Making changes with transactions" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uP1-Jc-o9v">
<rect key="frame" x="15" y="30" width="179.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -254,17 +305,21 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="C8Y-0y-lEG" detailTextLabel="jZw-qE-0ws" style="IBUITableViewCellStyleSubtitle" id="ph1-8z-C1m"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="C8Y-0y-lEG" detailTextLabel="jZw-qE-0ws" style="IBUITableViewCellStyleSubtitle" id="ph1-8z-C1m">
<rect key="frame" x="0.0" y="249" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ph1-8z-C1m" id="nNz-rd-ksg"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ph1-8z-C1m" id="nNz-rd-ksg">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Time Zones" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="C8Y-0y-lEG">
<rect key="frame" x="15" y="6" width="101.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Fetching objects and raw values" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jZw-qE-0ws"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Fetching objects and raw values" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jZw-qE-0ws">
<rect key="frame" x="15" y="30" width="169" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -277,17 +332,21 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="ZfY-Aq-Ykq" detailTextLabel="QzD-9b-k1j" style="IBUITableViewCellStyleSubtitle" id="wyK-rk-3tI"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="ZfY-Aq-Ykq" detailTextLabel="QzD-9b-k1j" style="IBUITableViewCellStyleSubtitle" id="wyK-rk-3tI">
<rect key="frame" x="0.0" y="299" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wyK-rk-3tI" id="fLd-KK-QcW"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wyK-rk-3tI" id="fLd-KK-QcW">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZfY-Aq-Ykq">
<rect key="frame" x="15" y="6" width="61" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Implementing a custom logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QzD-9b-k1j"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Implementing a custom logger" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QzD-9b-k1j">
<rect key="frame" x="15" y="30" width="159.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -300,17 +359,21 @@
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hSG-mG-YBw" detailTextLabel="X9P-TQ-LYh" style="IBUITableViewCellStyleSubtitle" id="xTM-Cf-0if"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hSG-mG-YBw" detailTextLabel="X9P-TQ-LYh" style="IBUITableViewCellStyleSubtitle" id="xTM-Cf-0if">
<rect key="frame" x="0.0" y="349" width="600" height="50"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xTM-Cf-0if" id="DfO-BW-krd"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xTM-Cf-0if" id="DfO-BW-krd">
<rect key="frame" x="0.0" y="0.0" width="567" height="49.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Evolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hSG-mG-YBw">
<rect key="frame" x="15" y="6" width="78.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Migrating and de-migrating stores" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X9P-TQ-LYh"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Migrating and de-migrating stores" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X9P-TQ-LYh">
<rect key="frame" x="15" y="30" width="179.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -345,18 +408,18 @@
<viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/> <viewControllerLayoutGuide type="bottom" id="aI4-O3-OCi"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="w8K-eN-RvU"> <view key="view" contentMode="scaleToFill" id="w8K-eN-RvU">
<rect key="frame" x="0.0" y="0.0" width="600" height="268"/> <rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd"> <view contentMode="scaleToFill" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="NhC-oM-bkd">
<rect key="frame" x="16" y="70" width="568" height="36"/> <rect key="frame" x="20" y="69.5" width="552" height="36.5"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints> <constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/> <constraint firstAttribute="height" relation="greaterThanOrEqual" id="TIX-qi-B34"/>
</constraints> </constraints>
</view> </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfe-Yq-3Xa"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfe-Yq-3Xa">
<rect key="frame" x="16" y="116" width="568" height="18"/> <rect key="frame" x="20" y="116" width="552" height="18"/>
<constraints> <constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/> <constraint firstAttribute="height" relation="greaterThanOrEqual" id="4h9-ha-EzR"/>
</constraints> </constraints>
@@ -365,43 +428,43 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hue" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sgg-Md-Nf3"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hue" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sgg-Md-Nf3">
<rect key="frame" x="16" y="154" width="74" height="18"/> <rect key="frame" x="20" y="154" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/> <fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Saturation" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rry-vh-bRK"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Saturation" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rry-vh-bRK">
<rect key="frame" x="16" y="192" width="74" height="18"/> <rect key="frame" x="20" y="192" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/> <fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Brightness" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vTa-ly-eyO"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Brightness" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vTa-ly-eyO">
<rect key="frame" x="16" y="230" width="74" height="18"/> <rect key="frame" x="20" y="230" width="74" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/> <fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb"> <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="359" translatesAutoresizingMaskIntoConstraints="NO" id="YQ6-fq-3Wb">
<rect key="frame" x="98" y="148" width="488" height="31"/> <rect key="frame" x="102" y="148" width="472" height="31"/>
<connections> <connections>
<action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/> <action selector="hueSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="9Hy-3h-llE"/>
</connections> </connections>
</slider> </slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xXz-78-tAd"> <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xXz-78-tAd">
<rect key="frame" x="98" y="186" width="488" height="31"/> <rect key="frame" x="102" y="186" width="472" height="31"/>
<connections> <connections>
<action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/> <action selector="saturationSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="qtU-ua-ZTc"/>
</connections> </connections>
</slider> </slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="hpy-2d-eOP"> <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="hpy-2d-eOP">
<rect key="frame" x="98" y="224" width="488" height="31"/> <rect key="frame" x="102" y="224" width="472" height="31"/>
<connections> <connections>
<action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/> <action selector="brightnessSliderValueDidChange:" destination="dX3-kR-CYC" eventType="valueChanged" id="F09-EP-2iD"/>
</connections> </connections>
</slider> </slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p4O-tf-dgt">
<rect key="frame" x="16" y="49" width="568" height="21"/> <rect key="frame" x="20" y="49" width="552" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@@ -469,17 +532,17 @@
<viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/> <viewControllerLayoutGuide type="bottom" id="LNL-mj-D7l"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="6x3-vn-Egt"> <view key="view" contentMode="scaleToFill" id="6x3-vn-Egt">
<rect key="frame" x="0.0" y="64" width="600" height="600"/> <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf"> <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L5f-tW-lXf">
<rect key="frame" x="0.0" y="64" width="600" height="268"/> <rect key="frame" x="4" y="64" width="592" height="268"/>
<connections> <connections>
<segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/> <segue destination="5Fw-je-9gI" kind="embed" id="YcI-2Z-ijV"/>
</connections> </connections>
</containerView> </containerView>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp"> <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6So-f3-4Gp">
<rect key="frame" x="0.0" y="332" width="600" height="268"/> <rect key="frame" x="4" y="332" width="592" height="268"/>
<connections> <connections>
<segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/> <segue destination="sll-yo-mBc" kind="embed" id="AAl-HS-dq2"/>
</connections> </connections>
@@ -535,12 +598,14 @@
<objects> <objects>
<tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController"> <tableViewController id="3AE-ED-0oj" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="DAz-BE-6Ca"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="DAz-BE-6Ca">
<rect key="frame" x="0.0" y="0.0" width="600" height="268"/> <rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="G3X-70-BCD" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="G3X-70-BCD" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="G3X-70-BCD" id="aT8-nz-i5l"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="G3X-70-BCD" id="aT8-nz-i5l">
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uQX-PI-UWF">
@@ -592,13 +657,15 @@
<objects> <objects>
<tableViewController id="lCE-i6-UCT" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController"> <tableViewController id="lCE-i6-UCT" customClass="ListObserverDemoViewController" customModule="CoreStoreDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Zba-8M-Zd7"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Zba-8M-Zd7">
<rect key="frame" x="0.0" y="0.0" width="600" height="268"/> <rect key="frame" x="0.0" y="0.0" width="592" height="268"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PaletteTableViewCell" id="zSO-3e-OVq" customClass="PaletteTableViewCell" customModule="CoreStoreDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="66" width="592" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zSO-3e-OVq" id="cHA-by-n4b">
<rect key="frame" x="0.0" y="0.0" width="559" height="43.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5uq-Yi-XwH">
@@ -679,7 +746,7 @@
<viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/> <viewControllerLayoutGuide type="bottom" id="RZg-hi-T8O"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="k4s-iL-Krh"> <view key="view" contentMode="scaleToFill" id="k4s-iL-Krh">
<rect key="frame" x="0.0" y="0.0" width="600" height="536"/> <rect key="frame" x="0.0" y="64" width="600" height="536"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0"> <mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="V2U-0R-Ts0">
@@ -832,12 +899,14 @@
</view> </view>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="6db-P0-6Ms" style="IBUITableViewCellStyleDefault" id="vUr-WV-qur"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="6db-P0-6Ms" style="IBUITableViewCellStyleDefault" id="vUr-WV-qur">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/> <rect key="frame" x="0.0" y="102" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vUr-WV-qur" id="Vr0-hE-cn9"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vUr-WV-qur" id="Vr0-hE-cn9">
<rect key="frame" x="0.0" y="0.0" width="567" height="43.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6db-P0-6Ms"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6db-P0-6Ms">
<rect key="frame" x="15" y="0.0" width="550" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -884,17 +953,21 @@
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="RgX-yK-1L2" detailTextLabel="QZ4-A2-x4h" style="IBUITableViewCellStyleSubtitle" id="uBt-Iy-nWP"> <tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="RgX-yK-1L2" detailTextLabel="QZ4-A2-x4h" style="IBUITableViewCellStyleSubtitle" id="uBt-Iy-nWP">
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uBt-Iy-nWP" id="6SD-ur-9zp"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uBt-Iy-nWP" id="6SD-ur-9zp">
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RgX-yK-1L2"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RgX-yK-1L2">
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QZ4-A2-x4h"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QZ4-A2-x4h">
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -926,17 +999,21 @@
<color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="separatorColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="Syt-QJ-KXg" detailTextLabel="yHS-dP-IKS" style="IBUITableViewCellStyleSubtitle" id="q7Q-aF-Ftl"> <tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="UITableViewCell" textLabel="Syt-QJ-KXg" detailTextLabel="yHS-dP-IKS" style="IBUITableViewCellStyleSubtitle" id="q7Q-aF-Ftl">
<rect key="frame" x="0.0" y="100" width="600" height="60"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q7Q-aF-Ftl" id="fc3-eg-yes"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q7Q-aF-Ftl" id="fc3-eg-yes">
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Syt-QJ-KXg"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="name" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Syt-QJ-KXg">
<rect key="frame" x="15" y="11" width="48.5" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/> <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yHS-dP-IKS"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="offset" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yHS-dP-IKS">
<rect key="frame" x="15" y="35" width="31" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/> <fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.17254901959999999" green="0.24313725489999999" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>

View File

@@ -25,7 +25,7 @@ private struct Static {
transaction.deleteAll(From(TimeZone)) transaction.deleteAll(From(TimeZone))
for name in NSTimeZone.knownTimeZoneNames() as! [String] { for name in NSTimeZone.knownTimeZoneNames() {
let rawTimeZone = NSTimeZone(name: name)! let rawTimeZone = NSTimeZone(name: name)!
let cachedTimeZone = transaction.create(Into(TimeZone)) let cachedTimeZone = transaction.create(Into(TimeZone))
@@ -112,7 +112,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell") as! UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")!
switch self.segmentedControl?.selectedSegmentIndex { switch self.segmentedControl?.selectedSegmentIndex {

View File

@@ -43,7 +43,7 @@ class FetchingResultsViewController: UITableViewController {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) as! UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
let timeZone = self.timeZones[indexPath.row] let timeZone = self.timeZones[indexPath.row]
cell.textLabel?.text = timeZone.name cell.textLabel?.text = timeZone.name

View File

@@ -62,7 +62,7 @@ class QueryingResultsViewController: UITableViewController {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) as! UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
let value = self.values[indexPath.row] let value = self.values[indexPath.row]

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.johnestropia.CoreStoreDemo</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@@ -176,10 +176,6 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
self.hsbLabel?.text = palette.colorText self.hsbLabel?.text = palette.colorText
let hue = palette.hue
let saturation = palette.saturation
let brightness = palette.brightness
if changedKeys == nil || changedKeys?.contains("hue") == true { if changedKeys == nil || changedKeys?.contains("hue") == true {
self.hueSlider?.value = Float(palette.hue) self.hueSlider?.value = Float(palette.hue)

View File

@@ -50,7 +50,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
// MARK: CoreStoreLogger // MARK: CoreStoreLogger
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) {
GCDQueue.Main.async { [weak self] in GCDQueue.Main.async { [weak self] in
@@ -66,7 +66,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
} }
} }
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) {
GCDQueue.Main.async { [weak self] in GCDQueue.Main.async { [weak self] in
@@ -87,6 +87,11 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
} }
} }
@noreturn func fatalError(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
Swift.fatalError("\(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Abort] \(message)")
}
// MARK: Private // MARK: Private
@@ -100,7 +105,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
case .Some(0): case .Some(0):
self.dataStack.beginAsynchronous { (transaction) -> Void in self.dataStack.beginAsynchronous { (transaction) -> Void in
transaction.create(Into(UserAccount)) transaction.create(Into(Palette))
} }
case .Some(1): case .Some(1):

View File

@@ -10,36 +10,6 @@ import UIKit
import CoreStore import CoreStore
private struct Static {
static let migrationStack: DataStack = {
let dataStack = DataStack(
modelName: "MigrationDemo",
modelVersions: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
dataStack.addSQLiteStoreAndWait(
"MigrationsDemo.sqlite",
automigrating: true, // default is true anyway
resetStoreOnMigrationFailure: true
)
dataStack.beginSynchronous { (transaction) -> Void in
transaction.deleteAll(From(OrganismV1))
let organism = transaction.create(Into(OrganismV1))
organism.hasHead = true
organism.hasTail = true
transaction.commit()
}
return dataStack
}()
}
// MARK: - MigrationsDemoViewController // MARK: - MigrationsDemoViewController
class MigrationsDemoViewController: UITableViewController { class MigrationsDemoViewController: UITableViewController {
@@ -62,7 +32,7 @@ class MigrationsDemoViewController: UITableViewController {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) as! UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
cell.textLabel?.text = self.models[indexPath.row].version cell.textLabel?.text = self.models[indexPath.row].version
return cell return cell
} }
@@ -83,12 +53,27 @@ class MigrationsDemoViewController: UITableViewController {
// MARK: Private // MARK: Private
private typealias ModelMetadata = (version: String, entityType: AnyClass) private typealias ModelMetadata = (version: String, entityType: AnyClass, migrationChain: MigrationChain)
private let models: [ModelMetadata] = [ private let models: [ModelMetadata] = [
(version: "MigrationDemo", entityType: OrganismV1.self), (
(version: "MigrationDemoV2", entityType: OrganismV2.self), version: "MigrationDemo",
(version: "MigrationDemoV3", entityType: OrganismV3.self) entityType: OrganismV1.self,
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
(
version: "MigrationDemoV2",
entityType: OrganismV2.self,
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
(
version: "MigrationDemoV3",
entityType: OrganismV3.self,
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
] ]
private var dataStack: DataStack? private var dataStack: DataStack?
@@ -124,56 +109,86 @@ class MigrationsDemoViewController: UITableViewController {
let dataStack = DataStack( let dataStack = DataStack(
modelName: "MigrationDemo", modelName: "MigrationDemo",
modelVersions: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"] migrationChain: model.migrationChain
) )
self.dataStack = dataStack
self.setEnabled(false)
dataStack.addSQLiteStore( dataStack.addSQLiteStore(
"MigrationDemo.sqlite", "MigrationDemo.sqlite",
completion: { [weak self] (result) -> Void in completion: { [weak self] (result) -> Void in
if let strongSelf = self { guard let strongSelf = self else {
if let organism = dataStack.fetchOne(From(model.entityType)) { return
strongSelf.organism = organism
}
else {
dataStack.beginSynchronous { (transaction) -> Void in
let organism = transaction.create(Into(model.entityType))
(organism as! OrganismProtocol).mutate()
transaction.commit()
}
strongSelf.organism = dataStack.fetchOne(From(model.entityType))!
}
strongSelf.updateDisplay()
strongSelf.tableView.selectRowAtIndexPath(
NSIndexPath(
forRow: find(
strongSelf.models.map { $0.version },
model.version
)!,
inSection: 0
),
animated: false,
scrollPosition: .None
)
} }
guard case .Success = result else {
strongSelf.setEnabled(true)
return
}
strongSelf.dataStack = dataStack
if let organism = dataStack.fetchOne(From(model.entityType)) {
strongSelf.organism = organism
}
else {
dataStack.beginSynchronous { (transaction) -> Void in
let organism = transaction.create(Into(model.entityType))
(organism as! OrganismProtocol).mutate()
transaction.commit()
}
strongSelf.organism = dataStack.fetchOne(From(model.entityType))!
}
strongSelf.updateDisplay()
strongSelf.tableView.selectRowAtIndexPath(
NSIndexPath(
forRow: strongSelf.models.map { $0.version }.indexOf(model.version)!,
inSection: 0
),
animated: false,
scrollPosition: .None
)
strongSelf.setEnabled(true)
} }
) )
} }
func setEnabled(enabled: Bool) {
UIView.animateKeyframesWithDuration(
0.2,
delay: 0,
options: .BeginFromCurrentState,
animations: { () -> Void in
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItem?.enabled = enabled
navigationItem.rightBarButtonItem?.enabled = enabled
navigationItem.backBarButtonItem?.enabled = enabled
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled
}
},
completion: nil
)
}
func updateDisplay() { func updateDisplay() {
var lines = [String]() var lines = [String]()
var organismType = "" var organismType = ""
if let organism = self.organism { if let organism = self.organism {
for property in organism.entity.properties as! [NSPropertyDescription] { for property in organism.entity.properties {
let value: AnyObject = organism.valueForKey(property.name) ?? NSNull() let value: AnyObject = organism.valueForKey(property.name) ?? NSNull()
lines.append("\(property.name): \(value)") lines.append("\(property.name): \(value)")

File diff suppressed because one or more lines are too long

View File

@@ -10,18 +10,14 @@ import CoreData
class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy { class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstancesForSourceInstance(sInstance: NSManagedObject, entityMapping mapping: NSEntityMapping, manager: NSMigrationManager, error: NSErrorPointer) -> Bool { override func createDestinationInstancesForSourceInstance(sInstance: NSManagedObject, entityMapping mapping: NSEntityMapping, manager: NSMigrationManager) throws {
if !super.createDestinationInstancesForSourceInstance(sInstance, entityMapping: mapping, manager: manager, error: error) { try super.createDestinationInstancesForSourceInstance(sInstance, entityMapping: mapping, manager: manager)
return false
}
for dInstance in manager.destinationInstancesForEntityMappingNamed(mapping.name, sourceInstances: [sInstance]) { for dInstance in manager.destinationInstancesForEntityMappingNamed(mapping.name, sourceInstances: [sInstance]) {
dInstance.setValue(false, forKey: "hasVertebrae") dInstance.setValue(false, forKey: "hasVertebrae")
dInstance.setValue(sInstance.valueForKey("numberOfFlippers"), forKey: "numberOfLimbs") dInstance.setValue(sInstance.valueForKey("numberOfFlippers"), forKey: "numberOfLimbs")
} }
return true
} }
} }

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14D136" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic"> <model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8118.20" systemVersion="14D136" minimumToolsVersion="Xcode 4.3">
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV2" syncable="YES"> <entity name="Organism" representedClassName="CoreStoreDemo.OrganismV2" syncable="YES">
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/> <attribute name="hasHead" attributeType="Boolean" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/> <attribute name="hasTail" attributeType="Boolean" syncable="YES"/>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14D136" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic"> <model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8118.20" systemVersion="14D136" minimumToolsVersion="Xcode 4.3">
<entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES"> <entity name="Organism" representedClassName="CoreStoreDemo.OrganismV3" syncable="YES">
<attribute name="hasHead" attributeType="Boolean" syncable="YES"/> <attribute name="hasHead" attributeType="Boolean" syncable="YES"/>
<attribute name="hasTail" attributeType="Boolean" syncable="YES"/> <attribute name="hasTail" attributeType="Boolean" syncable="YES"/>

View File

@@ -138,7 +138,7 @@ class StackSetupDemoViewController: UITableViewController {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell") as! UITableViewCell let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")!
let account = self.accounts[indexPath.section][indexPath.row] let account = self.accounts[indexPath.section][indexPath.row]
cell.textLabel?.text = account.name cell.textLabel?.text = account.name

View File

@@ -100,7 +100,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
// MARK: MKMapViewDelegate // MARK: MKMapViewDelegate
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! { func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MKAnnotationView" let identifier = "MKAnnotationView"
var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView
@@ -187,13 +187,13 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
self.geocoder?.cancelGeocode() self.geocoder?.cancelGeocode()
var geocoder = CLGeocoder() let geocoder = CLGeocoder()
self.geocoder = geocoder self.geocoder = geocoder
geocoder.reverseGeocodeLocation( geocoder.reverseGeocodeLocation(
CLLocation(latitude: place.latitude, longitude: place.longitude), CLLocation(latitude: place.latitude, longitude: place.longitude),
completionHandler: { [weak self] (placemarks, error) -> Void in completionHandler: { [weak self] (placemarks, error) -> Void in
if let strongSelf = self, let placemark = (placemarks as? [CLPlacemark])?.first { if let placemark = placemarks?.first {
let place = transaction.edit(Static.placeController.object) let place = transaction.edit(Static.placeController.object)
place?.title = placemark.name place?.title = placemark.name

View File

@@ -43,7 +43,7 @@ class CoreStoreTests: XCTestCase {
func testExample() { func testExample() {
let stack = DataStack(sourceBundles: NSBundle.allBundles() as? [NSBundle]) let stack = DataStack(modelName: "Model", sourceBundle: NSBundle(forClass: self.dynamicType))
CoreStore.defaultStack = stack CoreStore.defaultStack = stack
XCTAssert(CoreStore.defaultStack === stack, "CoreStore.defaultStack === stack") XCTAssert(CoreStore.defaultStack === stack, "CoreStore.defaultStack === stack")
@@ -187,7 +187,7 @@ class CoreStoreTests: XCTestCase {
Select("testString", .Count("testString", As: "count")), Select("testString", .Count("testString", As: "count")),
GroupBy("testString") GroupBy("testString")
) )
println(counts) print(counts)
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()") XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
switch result { switch result {
@@ -231,6 +231,18 @@ class CoreStoreTests: XCTestCase {
transaction.commit() transaction.commit()
} }
CoreStore.beginSynchronous({ (transaction) -> Void in
if let obj = CoreStore.fetchOne(From(TestEntity2)) {
let oldID = obj.testEntityID
obj.testEntityID = 0
obj.testEntityID = oldID
}
transaction.commit()
})
let objs1 = CoreStore.fetchAll(From(TestEntity1)) let objs1 = CoreStore.fetchAll(From(TestEntity1))
XCTAssertNotNil(objs1, "objs1 != nil") XCTAssertNotNil(objs1, "objs1 != nil")
XCTAssertTrue(objs1?.count == 0, "objs1?.count == 0") XCTAssertTrue(objs1?.count == 0, "objs1?.count == 0")
@@ -325,9 +337,12 @@ class CoreStoreTests: XCTestCase {
private func deleteStores() { private func deleteStores() {
NSFileManager.defaultManager().removeItemAtURL( do {
NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first as! NSURL,
error: nil try NSFileManager.defaultManager().removeItemAtURL(
) NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first!
)
}
catch _ { }
} }
} }

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@@ -55,8 +55,8 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
transaction.commit { (result) -> Void in transaction.commit { (result) -> Void in
switch result { switch result {
case .Success(let hasChanges): println("success!") case .Success(let hasChanges): print("success!")
case .Failure(let error): println(error) case .Failure(let error): print(error)
} }
} }
} }
@@ -145,9 +145,9 @@ let dataStack = DataStack(modelName: "MyModel") // loads from the "MyModel.xcdat
switch dataStack.addInMemoryStore(configuration: "Config1") { // creates an in-memory store with entities from the "Config1" configuration in the .xcdatamodeld file switch dataStack.addInMemoryStore(configuration: "Config1") { // creates an in-memory store with entities from the "Config1" configuration in the .xcdatamodeld file
case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance
println("Successfully created an in-memory store: \(persistentStore)" print("Successfully created an in-memory store: \(persistentStore)"
case .Failure(let error): // error is an NSError instance case .Failure(let error): // error is an NSError instance
println("Failed creating an in-memory store with error: \(error.description)" print("Failed creating an in-memory store with error: \(error.description)"
} }
switch dataStack.addSQLiteStoreAndWait( switch dataStack.addSQLiteStoreAndWait(
@@ -156,9 +156,9 @@ switch dataStack.addSQLiteStoreAndWait(
automigrating: true, // automatically run lightweight migrations or entity policy migrations when needed automigrating: true, // automatically run lightweight migrations or entity policy migrations when needed
resetStoreOnMigrationFailure: true) { // delete and recreate the sqlite file when migration conflicts occur (useful when debugging) resetStoreOnMigrationFailure: true) { // delete and recreate the sqlite file when migration conflicts occur (useful when debugging)
case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance
println("Successfully created an sqlite store: \(persistentStore)" print("Successfully created an sqlite store: \(persistentStore)"
case .Failure(let error): // error is an NSError instance case .Failure(let error): // error is an NSError instance
println("Failed creating an sqlite store with error: \(error.description)" print("Failed creating an sqlite store with error: \(error.description)"
} }
CoreStore.defaultStack = dataStack // pass the dataStack to CoreStore for easier access later on CoreStore.defaultStack = dataStack // pass the dataStack to CoreStore for easier access later on
@@ -177,7 +177,7 @@ class MyViewController: UIViewController {
} }
func methodToBeCalledLaterOn() { func methodToBeCalledLaterOn() {
let objects = self.dataStack.fetchAll(From(MyEntity)) let objects = self.dataStack.fetchAll(From(MyEntity))
println(objects) print(objects)
} }
} }
``` ```
@@ -190,7 +190,7 @@ class MyViewController: UIViewController {
} }
func methodToBeCalledLaterOn() { func methodToBeCalledLaterOn() {
let objects = CoreStore.fetchAll(From(MyEntity)) let objects = CoreStore.fetchAll(From(MyEntity))
println(objects) print(objects)
} }
} }
``` ```