mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-12 12:20:30 +01:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba4fb5e5cb | ||
|
|
d860da2507 | ||
|
|
2bcf8008c5 | ||
|
|
71477c0839 | ||
|
|
3348aa0bef | ||
|
|
2ed61fdb17 | ||
|
|
9cfad8a17a | ||
|
|
3bf34f33dc | ||
|
|
90bfaeaae8 | ||
|
|
a29a4b38fe | ||
|
|
5a96ef13f6 | ||
|
|
b92ee76907 | ||
|
|
67ccae4ef6 | ||
|
|
62b11309f3 | ||
|
|
8c6a7df731 | ||
|
|
b475afe79f | ||
|
|
a263851266 | ||
|
|
cbc3eb8887 | ||
|
|
2fb3263aa1 | ||
|
|
64aa97264e | ||
|
|
8066bf2a5a | ||
|
|
283104af3f | ||
|
|
83c724f584 | ||
|
|
59ad525786 | ||
|
|
b85d7521e1 | ||
|
|
4dbc4558e3 | ||
|
|
2a56c097f2 | ||
|
|
d4b95aed64 | ||
|
|
0d2650c54b | ||
|
|
6a3885edda | ||
|
|
1c6085ad82 |
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "1.0.1"
|
||||
s.version = "1.2.0"
|
||||
s.license = "MIT"
|
||||
s.summary = "Simple, elegant, and smart Core Data programming with Swift"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
B5D39A0419FD00DE000E91BB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D39A0319FD00DE000E91BB /* UIKit.framework */; };
|
||||
B5D5E0CF1A4D6AAB006468AF /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */; };
|
||||
B5D8080E1A3471A500A44484 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D808021A34715700A44484 /* GCDKit.framework */; };
|
||||
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */; };
|
||||
B5E834BB1B7691F3001D3D50 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834BA1B7691F3001D3D50 /* Functions.swift */; };
|
||||
B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDB1AFF84500064E85B /* DataStack.swift */; };
|
||||
B5E84EE11AFF84500064E85B /* PersistentStoreResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDE1AFF84500064E85B /* PersistentStoreResult.swift */; };
|
||||
B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE31AFF84610064E85B /* DefaultLogger.swift */; };
|
||||
@@ -126,6 +128,8 @@
|
||||
B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEntity2.swift; sourceTree = "<group>"; };
|
||||
B5D806C51A34715700A44484 /* GCDKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = GCDKit.xcodeproj; sourceTree = "<group>"; };
|
||||
B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = CoreStore.podspec; sourceTree = SOURCE_ROOT; };
|
||||
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BaseDataTransaction+Importing.swift"; sourceTree = "<group>"; };
|
||||
B5E834BA1B7691F3001D3D50 /* Functions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functions.swift; sourceTree = "<group>"; };
|
||||
B5E84ED81AFF82360064E85B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
|
||||
B5E84ED91AFF82360064E85B /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; };
|
||||
B5E84EDB1AFF84500064E85B /* DataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStack.swift; sourceTree = "<group>"; };
|
||||
@@ -221,6 +225,7 @@
|
||||
B5E84EDA1AFF84500064E85B /* Setting Up */,
|
||||
B5E84EE21AFF84610064E85B /* Logging */,
|
||||
B5E84EE91AFF846E0064E85B /* Saving and Processing */,
|
||||
B5E834B61B7630BD001D3D50 /* Importing Data */,
|
||||
B5E84EFD1AFF847B0064E85B /* Fetching and Querying */,
|
||||
B5E84F191AFF84860064E85B /* Observing */,
|
||||
B56964D11B22FF700075EE4A /* Migrating */,
|
||||
@@ -309,6 +314,14 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5E834B61B7630BD001D3D50 /* Importing Data */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */,
|
||||
);
|
||||
path = "Importing Data";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B5E84EDA1AFF84500064E85B /* Setting Up */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -414,6 +427,7 @@
|
||||
B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */,
|
||||
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */,
|
||||
B5E84F2D1AFF849C0064E85B /* WeakObject.swift */,
|
||||
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
|
||||
);
|
||||
path = Internal;
|
||||
sourceTree = "<group>";
|
||||
@@ -578,6 +592,7 @@
|
||||
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */,
|
||||
B5E84EF61AFF846E0064E85B /* DataStack+Transaction.swift in Sources */,
|
||||
B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */,
|
||||
B5E834BB1B7691F3001D3D50 /* Functions.swift in Sources */,
|
||||
B5E84F231AFF84860064E85B /* ListMonitor.swift in Sources */,
|
||||
B5E84EF71AFF846E0064E85B /* DetachedDataTransaction.swift in Sources */,
|
||||
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */,
|
||||
@@ -597,6 +612,7 @@
|
||||
B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */,
|
||||
B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */,
|
||||
B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */,
|
||||
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */,
|
||||
B5E84EE61AFF84610064E85B /* DefaultLogger.swift in Sources */,
|
||||
B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */,
|
||||
B5E84F151AFF847B0064E85B /* CoreStore+Querying.swift in Sources */,
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForRunning = "NO"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
buildForAnalyzing = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
|
||||
|
||||
@@ -58,4 +58,20 @@ public extension NSManagedObject {
|
||||
self.setPrimitiveValue(value, forKey: KVCKey)
|
||||
self.didChangeValueForKey(KVCKey)
|
||||
}
|
||||
|
||||
/**
|
||||
Re-faults the object to use the latest values from the persistent store
|
||||
*/
|
||||
public func refreshAsFault() {
|
||||
|
||||
self.managedObjectContext?.refreshObject(self, mergeChanges: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Re-faults the object to use the latest values from the persistent store and merges previously pending changes back
|
||||
*/
|
||||
public func refreshAndMerge() {
|
||||
|
||||
self.managedObjectContext?.refreshObject(self, mergeChanges: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,84 @@ public extension BaseDataTransaction {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter object: a reference to the object created/fetched outside the transaction
|
||||
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
|
||||
|
||||
do {
|
||||
|
||||
return (try self.context.existingObjectWithID(object.objectID) as! T)
|
||||
}
|
||||
catch _ {
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instance in the transaction's context from an `NSManagedObjectID`.
|
||||
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
do {
|
||||
|
||||
return (try self.context.existingObjectWithID(objectID) as! T)
|
||||
}
|
||||
catch _ {
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instances in the transaction's context from references created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
|
||||
- returns: the `NSManagedObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
|
||||
|
||||
var existingObjects = [T]()
|
||||
for object in objects {
|
||||
|
||||
do {
|
||||
|
||||
let existingObject = try self.context.existingObjectWithID(object.objectID) as! T
|
||||
existingObjects.append(existingObject)
|
||||
}
|
||||
catch _ { }
|
||||
}
|
||||
return existingObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instances in the transaction's context from a list of `NSManagedObjectID`.
|
||||
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `NSManagedObject` array for objects that exists in the transaction
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
|
||||
|
||||
var existingObjects = [T]()
|
||||
for objectID in objectIDs {
|
||||
|
||||
do {
|
||||
|
||||
let existingObject = try self.context.existingObjectWithID(objectID) as! T
|
||||
existingObjects.append(existingObject)
|
||||
}
|
||||
catch _ { }
|
||||
}
|
||||
return existingObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
|
||||
@@ -43,7 +121,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -60,7 +138,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -77,7 +155,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -94,7 +172,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -111,7 +189,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -128,7 +206,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -145,7 +223,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -162,7 +240,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -179,7 +257,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -196,7 +274,7 @@ public extension BaseDataTransaction {
|
||||
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to fetch from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -213,7 +291,7 @@ public extension BaseDataTransaction {
|
||||
public func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: DeleteClause...) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to delete from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -230,7 +308,7 @@ public extension BaseDataTransaction {
|
||||
public func deleteAll<T: NSManagedObject>(from: From<T>, _ deleteClauses: [DeleteClause]) -> Int? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to delete from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -250,7 +328,7 @@ public extension BaseDataTransaction {
|
||||
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to query from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -270,7 +348,7 @@ public extension BaseDataTransaction {
|
||||
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to query from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -290,7 +368,7 @@ public extension BaseDataTransaction {
|
||||
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to query from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
@@ -310,7 +388,7 @@ public extension BaseDataTransaction {
|
||||
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to query from a \(typeName(self)) outside its designated queue."
|
||||
)
|
||||
|
||||
|
||||
@@ -31,6 +31,50 @@ public extension CoreStore {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, fetches the `NSManagedObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter object: a reference to the object created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(object: T) -> T? {
|
||||
|
||||
return self.defaultStack.fetchExisting(object)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, fetches the `NSManagedObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
|
||||
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
return self.defaultStack.fetchExisting(objectID)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, fetches the `NSManagedObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
|
||||
|
||||
return self.defaultStack.fetchExisting(objects)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, fetches the `NSManagedObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
|
||||
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public static func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
|
||||
|
||||
return self.defaultStack.fetchExisting(objectIDs)
|
||||
}
|
||||
|
||||
/**
|
||||
Using the `defaultStack`, fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
|
||||
|
||||
@@ -34,6 +34,84 @@ public extension DataStack {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter object: a reference to the object created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
|
||||
|
||||
do {
|
||||
|
||||
return (try self.mainContext.existingObjectWithID(object.objectID) as! T)
|
||||
}
|
||||
catch _ {
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instance in the `DataStack`'s context from an `NSManagedObjectID`.
|
||||
|
||||
- parameter objectID: the `NSManagedObjectID` for the object
|
||||
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
|
||||
|
||||
do {
|
||||
|
||||
return (try self.mainContext.existingObjectWithID(objectID) as! T)
|
||||
}
|
||||
catch _ {
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instances in the `DataStack`'s context from references created from a transaction or from a different managed object context.
|
||||
|
||||
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
|
||||
|
||||
var existingObjects = [T]()
|
||||
for object in objects {
|
||||
|
||||
do {
|
||||
|
||||
let existingObject = try self.mainContext.existingObjectWithID(object.objectID) as! T
|
||||
existingObjects.append(existingObject)
|
||||
}
|
||||
catch _ { }
|
||||
}
|
||||
return existingObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the `NSManagedObject` instances in the `DataStack`'s context from a list of `NSManagedObjectID`.
|
||||
|
||||
- parameter objectIDs: the `NSManagedObjectID` array for the objects
|
||||
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
|
||||
*/
|
||||
public func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
|
||||
|
||||
var existingObjects = [T]()
|
||||
for objectID in objectIDs {
|
||||
|
||||
do {
|
||||
|
||||
let existingObject = try self.mainContext.existingObjectWithID(objectID) as! T
|
||||
existingObjects.append(existingObject)
|
||||
}
|
||||
catch _ { }
|
||||
}
|
||||
return existingObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
|
||||
|
||||
289
CoreStore/Importing Data/BaseDataTransaction+Importing.swift
Normal file
289
CoreStore/Importing Data/BaseDataTransaction+Importing.swift
Normal file
@@ -0,0 +1,289 @@
|
||||
//
|
||||
// BaseDataTransaction+Importing.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2015 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
public protocol ImportableObject: class {
|
||||
|
||||
typealias ImportSource
|
||||
|
||||
static func shouldImportFromSource(source: ImportSource) -> Bool
|
||||
|
||||
func didInsertFromImportSource(source: ImportSource) throws
|
||||
|
||||
func updateFromImportSource(source: ImportSource) throws
|
||||
}
|
||||
|
||||
public extension ImportableObject {
|
||||
|
||||
static func shouldImportFromSource(source: ImportSource) -> Bool {
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public protocol ImportableUniqueObject: ImportableObject {
|
||||
|
||||
typealias UniqueIDType: NSObject
|
||||
|
||||
static var uniqueIDKeyPath: String { get }
|
||||
|
||||
var uniqueIDValue: UniqueIDType { get set }
|
||||
|
||||
static func uniqueIDFromImportSource(source: ImportSource) throws -> UniqueIDType
|
||||
}
|
||||
|
||||
|
||||
public extension BaseDataTransaction {
|
||||
|
||||
func importObject<T where T: NSManagedObject, T: ImportableObject>(
|
||||
into: Into<T>,
|
||||
source: T.ImportSource) throws -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
if !T.shouldImportFromSource(source) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsertFromImportSource(source)
|
||||
return object
|
||||
}
|
||||
}
|
||||
|
||||
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
||||
into: Into<T>,
|
||||
sourceArray: [T.ImportSource]) throws {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
for source in sourceArray {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsertFromImportSource(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
||||
into: Into<T>,
|
||||
sourceArray: [T.ImportSource],
|
||||
postProcess: (sorted: [T]) -> Void) throws {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
var objects = [T]()
|
||||
for source in sourceArray {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
try object.didInsertFromImportSource(source)
|
||||
|
||||
objects.append(object)
|
||||
}
|
||||
}
|
||||
postProcess(sorted: objects)
|
||||
}
|
||||
}
|
||||
|
||||
func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||
into: Into<T>,
|
||||
source: T.ImportSource) throws -> T? {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
return try autoreleasepool {
|
||||
|
||||
if !T.shouldImportFromSource(source) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let uniqueIDKeyPath = T.uniqueIDKeyPath
|
||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
||||
|
||||
if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
||||
|
||||
try object.updateFromImportSource(source)
|
||||
return object
|
||||
}
|
||||
else {
|
||||
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = uniqueIDValue
|
||||
try object.didInsertFromImportSource(source)
|
||||
return object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||
into: Into<T>,
|
||||
sourceArray: [T.ImportSource],
|
||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil) throws {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>()
|
||||
for source in sourceArray {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
if !T.shouldImportFromSource(source) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
||||
mapping[uniqueIDValue] = source
|
||||
}
|
||||
}
|
||||
|
||||
if let preProcess = preProcess {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
try preProcess(mapping: mapping)
|
||||
}
|
||||
}
|
||||
|
||||
for object in self.fetchAll(From(T), Where("%K IN %@", T.uniqueIDKeyPath, mapping.keys.array)) ?? [] {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let uniqueIDValue = object.uniqueIDValue
|
||||
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
|
||||
}
|
||||
}
|
||||
|
||||
for (uniqueIDValue, source) in mapping {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = uniqueIDValue
|
||||
try object.didInsertFromImportSource(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||
into: Into<T>,
|
||||
sourceArray: [T.ImportSource],
|
||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil,
|
||||
postProcess: (sorted: [T]) -> Void) throws {
|
||||
|
||||
CoreStore.assert(
|
||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
|
||||
)
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
var sortedIDs = Array<T.UniqueIDType>()
|
||||
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>()
|
||||
for source in sourceArray {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
if !T.shouldImportFromSource(source) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
||||
mapping[uniqueIDValue] = source
|
||||
sortedIDs.append(uniqueIDValue)
|
||||
}
|
||||
}
|
||||
|
||||
if let preProcess = preProcess {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
try preProcess(mapping: mapping)
|
||||
}
|
||||
}
|
||||
|
||||
var objects = Dictionary<T.UniqueIDType, T>()
|
||||
for object in self.fetchAll(From(T), Where("%K IN %@", T.uniqueIDKeyPath, mapping.keys.array)) ?? [] {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let uniqueIDValue = object.uniqueIDValue
|
||||
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
|
||||
objects[uniqueIDValue] = object
|
||||
}
|
||||
}
|
||||
|
||||
for (uniqueIDValue, source) in mapping {
|
||||
|
||||
try autoreleasepool {
|
||||
|
||||
let object = self.create(into)
|
||||
object.uniqueIDValue = uniqueIDValue
|
||||
try object.didInsertFromImportSource(source)
|
||||
|
||||
objects[uniqueIDValue] = object
|
||||
}
|
||||
}
|
||||
|
||||
postProcess(sorted: sortedIDs.flatMap { objects[$0] })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.1</string>
|
||||
<string>1.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
81
CoreStore/Internal/Functions.swift
Normal file
81
CoreStore/Internal/Functions.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Functions.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright (c) 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal func autoreleasepool<T>(@noescape closure: () -> T?) -> T? {
|
||||
|
||||
var closureValue: T?
|
||||
ObjectiveC.autoreleasepool {
|
||||
|
||||
closureValue = closure()
|
||||
}
|
||||
|
||||
return closureValue
|
||||
}
|
||||
|
||||
internal func autoreleasepool<T>(@noescape closure: () throws -> T?) throws -> T? {
|
||||
|
||||
var closureValue: T?
|
||||
var closureError: ErrorType?
|
||||
ObjectiveC.autoreleasepool {
|
||||
|
||||
do {
|
||||
|
||||
closureValue = try closure()
|
||||
}
|
||||
catch {
|
||||
|
||||
closureError = error
|
||||
}
|
||||
}
|
||||
|
||||
if let closureError = closureError {
|
||||
|
||||
throw closureError
|
||||
}
|
||||
return closureValue
|
||||
}
|
||||
|
||||
internal func autoreleasepool(@noescape closure: () throws -> Void) throws {
|
||||
|
||||
var closureError: ErrorType?
|
||||
ObjectiveC.autoreleasepool {
|
||||
|
||||
do {
|
||||
|
||||
try closure()
|
||||
}
|
||||
catch {
|
||||
|
||||
closureError = error
|
||||
}
|
||||
}
|
||||
|
||||
if let closureError = closureError {
|
||||
|
||||
throw closureError
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,15 @@ internal extension NSManagedObjectModel {
|
||||
return self.entityNameMapping[NSStringFromClass(entityClass)]!
|
||||
}
|
||||
|
||||
@nonobjc internal func entityMapping() -> [String: NSManagedObject.Type] {
|
||||
|
||||
return self.entityNameMapping.reduce([:]) { (var mapping, pair) in
|
||||
|
||||
mapping[pair.0] = (NSClassFromString(pair.1)! as! NSManagedObject.Type)
|
||||
return mapping
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc internal func mergedModels() -> [NSManagedObjectModel] {
|
||||
|
||||
return self.modelVersions?.map { self[$0] }.flatMap { $0 == nil ? [] : [$0!] } ?? [self]
|
||||
|
||||
@@ -62,21 +62,26 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
icon = "❗"
|
||||
levelString = "Fatal"
|
||||
}
|
||||
Swift.print("\(icon) [CoreStore: \(levelString)] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
|
||||
Swift.print("\(icon) [CoreStore: \(levelString)] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
|
||||
#endif
|
||||
}
|
||||
|
||||
public func handleError(error error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
#if DEBUG
|
||||
Swift.print("⚠️ [CoreStore: Error] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n \(error)\n")
|
||||
Swift.print("⚠️ [CoreStore: Error] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n \(error)\n")
|
||||
#endif
|
||||
}
|
||||
|
||||
public func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
#if DEBUG
|
||||
Swift.assert(condition, "❗ [CoreStore: Assertion Failure] \(message)", file: fileName, line: numericCast(lineNumber))
|
||||
if condition() {
|
||||
|
||||
return
|
||||
}
|
||||
Swift.print("❗ [CoreStore: Assertion Failure] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
|
||||
Swift.fatalError()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,15 +38,17 @@ public extension CoreStore {
|
||||
- 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. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
|
||||
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
|
||||
- parameter resetStoreOnModelMismatch: Set to true to delete the store on model mismatch; or set to false to report 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 completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
|
||||
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
|
||||
*/
|
||||
public static func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
|
||||
public static func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
|
||||
|
||||
return try self.defaultStack.addSQLiteStore(
|
||||
fileName: fileName,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles,
|
||||
resetStoreOnModelMismatch: resetStoreOnModelMismatch,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
@@ -57,15 +59,17 @@ public extension CoreStore {
|
||||
- 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. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
|
||||
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
|
||||
- parameter resetStoreOnModelMismatch: Set to true to delete the store on model mismatch; or set to false to report 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 completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `PersistentStoreResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
|
||||
- returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
|
||||
*/
|
||||
public static func addSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
|
||||
public static func addSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
|
||||
|
||||
return try self.defaultStack.addSQLiteStore(
|
||||
fileURL: fileURL,
|
||||
configuration: configuration,
|
||||
mappingModelBundles: mappingModelBundles,
|
||||
resetStoreOnModelMismatch: resetStoreOnModelMismatch,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ListMonitor<T> {
|
||||
public static func monitorList<T: NSManagedObject>(from: From<T>, _ queryClauses: FetchClause...) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, queryClauses)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public extension CoreStore {
|
||||
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
|
||||
- returns: a `ListMonitor` instance that monitors changes to the list
|
||||
*/
|
||||
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
public static func monitorList<T: NSManagedObject>(from: From<T>, _ queryClauses: [FetchClause]) -> ListMonitor<T> {
|
||||
|
||||
return self.defaultStack.monitorList(from, queryClauses)
|
||||
}
|
||||
|
||||
@@ -72,9 +72,10 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
// MARK: Public
|
||||
|
||||
/**
|
||||
Accesses the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `addObserver(_:)`.
|
||||
Returns the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `monitorList(_:)`.
|
||||
|
||||
- parameter index: the index of the object. Using an index above the valid range will throw an exception.
|
||||
- returns: the `NSManagedObject` at the specified index
|
||||
*/
|
||||
public subscript(index: Int) -> T {
|
||||
|
||||
@@ -82,10 +83,22 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
}
|
||||
|
||||
/**
|
||||
Accesses the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
|
||||
Returns the object at the given index, or `nil` if out of bounds. This subscript indexer is typically used for `ListMonitor`s created with `monitorList(_:)`.
|
||||
|
||||
- parameter index: the index for the object. Using an index above the valid range will return `nil`.
|
||||
- returns: the `NSManagedObject` at the specified index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndex index: Int) -> T? {
|
||||
|
||||
return self[safeSectionIndex: 0, safeItemIndex: index]
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
|
||||
|
||||
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will throw an exception.
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will throw an exception.
|
||||
- returns: the `NSManagedObject` at the specified section and item index
|
||||
*/
|
||||
public subscript(sectionIndex: Int, itemIndex: Int) -> T {
|
||||
|
||||
@@ -93,43 +106,173 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
}
|
||||
|
||||
/**
|
||||
Accesses the object at the given `NSIndexPath`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
|
||||
Returns the object at the given section and item index, or `nil` if out of bounds. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
|
||||
|
||||
- parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
|
||||
- parameter itemIndex: the index for the object within the section. Using an `itemIndex` with an invalid range will return `nil`.
|
||||
- returns: the `NSManagedObject` at the specified section and item index, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> T? {
|
||||
|
||||
guard let sections = self.fetchedResultsController.sections
|
||||
where sectionIndex < sections.count else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let section = sections[sectionIndex]
|
||||
guard itemIndex < section.numberOfObjects else {
|
||||
|
||||
return nil
|
||||
}
|
||||
return sections[sectionIndex].objects?[itemIndex] as? T
|
||||
}
|
||||
|
||||
/**
|
||||
Returns 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.
|
||||
- returns: the `NSManagedObject` at the specified index path
|
||||
*/
|
||||
public subscript(indexPath: NSIndexPath) -> T {
|
||||
|
||||
return self.fetchedResultsController.objectAtIndexPath(indexPath) as! T
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the object at the given `NSIndexPath`, or `nil` if out of bounds. 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 return `nil`.
|
||||
- returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
|
||||
*/
|
||||
public subscript(safeIndexPath indexPath: NSIndexPath) -> T? {
|
||||
|
||||
return self[safeSectionIndex: indexPath.section, safeItemIndex: indexPath.item]
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the `ListMonitor` has at least one object in any section.
|
||||
|
||||
- returns: `true` if at least one object in any section exists, `false` otherwise
|
||||
*/
|
||||
public func hasObjects() -> Bool {
|
||||
|
||||
return self.numberOfObjects() > 0
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the `ListMonitor` has at least one object the specified section.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `false`.
|
||||
- returns: `true` if at least one object in the specified section exists, `false` otherwise
|
||||
*/
|
||||
public func hasObjectsInSection(section: Int) -> Bool {
|
||||
|
||||
return self.numberOfObjectsInSection(safeSectionIndex: section) > 0
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in all sections
|
||||
|
||||
- returns: all objects in all sections
|
||||
*/
|
||||
public func objectsInAllSections() -> [T] {
|
||||
|
||||
return (self.fetchedResultsController.fetchedObjects as? [T]) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will throw an exception.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(section: Int) -> [T] {
|
||||
|
||||
return (self.fetchedResultsController.sections?[section].objects as? [T]) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all objects in the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: all objects in the specified section
|
||||
*/
|
||||
public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
|
||||
|
||||
return (self.fetchedResultsController.sections?[section].objects as? [T]) ?? []
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of sections
|
||||
|
||||
- returns: the number of sections
|
||||
*/
|
||||
public func numberOfSections() -> Int {
|
||||
|
||||
return self.fetchedResultsController.sections?.count ?? 0
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of objects in all sections
|
||||
|
||||
- returns: the number of objects in all sections
|
||||
*/
|
||||
public func numberOfObjects() -> Int {
|
||||
|
||||
return self.fetchedResultsController.fetchedObjects?.count ?? 0
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of objects in the specified section
|
||||
|
||||
- parameter section: the section index
|
||||
- parameter section: the section index. Using an index outside the valid range will throw an exception.
|
||||
- returns: the number of objects in the specified section
|
||||
*/
|
||||
public func numberOfObjectsInSection(section: Int) -> Int {
|
||||
|
||||
return self.fetchedResultsController.sections?[section].numberOfObjects ?? 0
|
||||
return self.sectionInfoAtIndex(section).numberOfObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of objects in the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: the number of objects in the specified section
|
||||
*/
|
||||
public func numberOfObjectsInSection(safeSectionIndex section: Int) -> Int? {
|
||||
|
||||
return self.sectionInfoAtIndex(safeSectionIndex: section)?.numberOfObjects
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSFetchedResultsSectionInfo` for the specified section
|
||||
|
||||
- parameter section: the section index
|
||||
- parameter section: the section index. Using an index outside the valid range will throw an exception.
|
||||
- returns: the `NSFetchedResultsSectionInfo` for the specified section
|
||||
*/
|
||||
public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
|
||||
|
||||
return self.fetchedResultsController.sections![section]
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if out of bounds.
|
||||
|
||||
- parameter section: the section index. Using an index outside the valid range will return `nil`.
|
||||
- returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
|
||||
*/
|
||||
public func sectionInfoAtIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
|
||||
|
||||
guard let sections = self.fetchedResultsController.sections
|
||||
where section < sections.count else {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return sections[section]
|
||||
}
|
||||
|
||||
/**
|
||||
Registers a `ListObserver` to be notified when changes to the receiver's list occur.
|
||||
|
||||
@@ -586,6 +729,16 @@ public final class ListMonitor<T: NSManagedObject> {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListMonitor: Equatable
|
||||
|
||||
public func ==<T: NSManagedObject>(lhs: ListMonitor<T>, rhs: ListMonitor<T>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
extension ListMonitor: Equatable { }
|
||||
|
||||
|
||||
// MARK: - ListMonitor: FetchedResultsControllerHandler
|
||||
|
||||
extension ListMonitor: FetchedResultsControllerHandler {
|
||||
@@ -723,7 +876,7 @@ private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResults
|
||||
self.handler?.controllerDidChangeContent(controller)
|
||||
}
|
||||
|
||||
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: NSManagedObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
|
||||
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
|
||||
|
||||
self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath)
|
||||
}
|
||||
|
||||
@@ -60,6 +60,19 @@ public protocol ListObserver: class {
|
||||
func listMonitorDidChange(monitor: ListMonitor<EntityType>)
|
||||
}
|
||||
|
||||
public extension ListObserver {
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitorWillChange(monitor: ListMonitor<EntityType>) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitorDidChange(monitor: ListMonitor<EntityType>) { }
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListObjectObserver
|
||||
|
||||
@@ -112,6 +125,29 @@ public protocol ListObjectObserver: ListObserver {
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
|
||||
}
|
||||
|
||||
public extension ListObjectObserver {
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { }
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ListSectionObserver
|
||||
|
||||
@@ -145,3 +181,16 @@ public protocol ListSectionObserver: ListObjectObserver {
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
||||
}
|
||||
|
||||
public extension ListSectionObserver {
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
|
||||
}
|
||||
|
||||
@@ -261,6 +261,16 @@ public final class ObjectMonitor<T: NSManagedObject> {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - ObjectMonitor: Equatable
|
||||
|
||||
public func ==<T: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
|
||||
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
extension ObjectMonitor: Equatable { }
|
||||
|
||||
|
||||
// MARK: - ObjectMonitor: FetchedResultsControllerHandler
|
||||
|
||||
extension ObjectMonitor: FetchedResultsControllerHandler {
|
||||
@@ -321,7 +331,7 @@ private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResults
|
||||
self.handler?.controllerWillChangeContent(controller)
|
||||
}
|
||||
|
||||
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: NSManagedObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
|
||||
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
|
||||
|
||||
self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath)
|
||||
}
|
||||
|
||||
@@ -67,3 +67,22 @@ public protocol ObjectObserver: class {
|
||||
*/
|
||||
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType)
|
||||
}
|
||||
|
||||
|
||||
public extension ObjectObserver {
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func objectMonitor(monitor: ObjectMonitor<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>) { }
|
||||
|
||||
/**
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType) { }
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public extension DataStack {
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
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.
|
||||
|
||||
- returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made.
|
||||
*/
|
||||
@@ -70,6 +70,10 @@ public extension DataStack {
|
||||
|
||||
return DetachedDataTransaction(
|
||||
mainContext: self.rootSavingContext,
|
||||
queue: .Main)
|
||||
queue: .createSerial(
|
||||
"com.coreStore.dataStack.detachedTransactionQueue",
|
||||
targetQueue: .UserInitiated
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,31 @@ public final class DetachedDataTransaction: BaseDataTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
|
||||
|
||||
- returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made.
|
||||
*/
|
||||
public func beginDetached() -> DetachedDataTransaction {
|
||||
|
||||
return DetachedDataTransaction(
|
||||
mainContext: self.context,
|
||||
queue: self.transactionQueue
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSManagedObjectContext` for this detached transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with.
|
||||
|
||||
Note that it is the developer's responsibility to ensure the following:
|
||||
- that the `DetachedDataTransaction` that owns this context should be strongly referenced and prevented from being deallocated during the context's lifetime
|
||||
- that all saves will be done either through the `DetachedDataTransaction`'s `commit(...)` method, or by calling `save()` manually on the context, its parent, and all other ancestor contexts if there are any.
|
||||
*/
|
||||
public var internalContext: NSManagedObjectContext {
|
||||
|
||||
return self.context
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
|
||||
@@ -32,6 +32,22 @@ import GCDKit
|
||||
|
||||
public extension CoreStore {
|
||||
|
||||
/**
|
||||
Returns the `defaultStack`'s model version. The version string is the same as the name of the version-specific .xcdatamodeld file.
|
||||
*/
|
||||
public static var modelVersion: String {
|
||||
|
||||
return self.defaultStack.modelVersion
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||
*/
|
||||
public static var entitiesByName: [String: NSManagedObject.Type] {
|
||||
|
||||
return self.defaultStack.entitiesByName
|
||||
}
|
||||
|
||||
/**
|
||||
Adds an in-memory store to the `defaultStack`.
|
||||
|
||||
|
||||
@@ -81,6 +81,22 @@ public final class DataStack {
|
||||
return self.model.currentModelVersion!
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public var entitiesByName: [String: NSManagedObject.Type] {
|
||||
|
||||
return self.model.entityMapping()
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `NSManagedObjectID` for the specified object URI if it exists in the persistent store.
|
||||
*/
|
||||
public func objectIDForURIRepresentation(url: NSURL) -> NSManagedObjectID? {
|
||||
|
||||
return self.coordinator.managedObjectIDForURIRepresentation(url)
|
||||
}
|
||||
|
||||
/**
|
||||
Adds an in-memory store to the stack.
|
||||
|
||||
@@ -259,7 +275,7 @@ public final class DataStack {
|
||||
internal let mainContext: NSManagedObjectContext
|
||||
internal let model: NSManagedObjectModel
|
||||
internal let migrationChain: MigrationChain
|
||||
internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue")
|
||||
internal let childTransactionQueue: GCDQueue = .createSerial("com.coreStore.dataStack.childTransactionQueue")
|
||||
internal let migrationQueue: NSOperationQueue = {
|
||||
|
||||
let migrationQueue = NSOperationQueue()
|
||||
|
||||
@@ -80,11 +80,6 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
|
||||
|
||||
// MARK: ObjectObserver
|
||||
|
||||
func objectMonitor(monitor: ObjectMonitor<Palette>, willUpdateObject object: Palette) {
|
||||
|
||||
// none
|
||||
}
|
||||
|
||||
func objectMonitor(monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPath>) {
|
||||
|
||||
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
|
||||
|
||||
@@ -62,7 +62,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
case .Warning: levelString = "Warning"
|
||||
case .Fatal: levelString = "Fatal"
|
||||
}
|
||||
self?.textView?.insertText("\(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
|
||||
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
|
||||
GCDQueue.Main.async { [weak self] in
|
||||
|
||||
self?.textView?.insertText("\(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
|
||||
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,13 +83,13 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger {
|
||||
|
||||
GCDQueue.Main.async { [weak self] in
|
||||
|
||||
self?.textView?.insertText("\(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(message)\n\n")
|
||||
self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(message)\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
@noreturn func fatalError(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
Swift.fatalError("\(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Abort] \(message)")
|
||||
Swift.fatalError("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Abort] \(message)")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,15 @@ class MigrationsDemoViewController: UIViewController {
|
||||
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
let alert = UIAlertController(
|
||||
title: "Migrations Demo",
|
||||
message: "This demo shows how to run incremental migrations and how to support multiple model versions in a single project.\n\nThe persistent store contains 10000 organisms, which gain/lose properties when the migration evolves/devolves them.\n\nYou can use the \"mutate\" button to change an organism's properties then migrate to a different model to see how its value gets affected.",
|
||||
preferredStyle: .Alert
|
||||
)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
|
||||
self.presentViewController(alert, animated: true, completion: nil)
|
||||
|
||||
|
||||
let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) {
|
||||
(dataStack: DataStack) -> ModelMetadata in
|
||||
|
||||
|
||||
Reference in New Issue
Block a user