mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-31 06:33:06 +02:00
WIP: documentation
This commit is contained in:
@@ -66,6 +66,8 @@
|
|||||||
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */; };
|
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */; };
|
||||||
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
|
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
|
||||||
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
|
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
|
||||||
|
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; settings = {ASSET_TAGS = (); }; };
|
||||||
|
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; settings = {ASSET_TAGS = (); }; };
|
||||||
B5FAD6A91B50A4B400714891 /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; };
|
B5FAD6A91B50A4B400714891 /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; };
|
||||||
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; };
|
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; };
|
||||||
B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; };
|
B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; };
|
||||||
@@ -169,6 +171,8 @@
|
|||||||
B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Transaction.swift"; sourceTree = "<group>"; };
|
B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Transaction.swift"; sourceTree = "<group>"; };
|
||||||
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Querying.swift"; sourceTree = "<group>"; };
|
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Querying.swift"; sourceTree = "<group>"; };
|
||||||
B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClauseTypes.swift; sourceTree = "<group>"; };
|
B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClauseTypes.swift; sourceTree = "<group>"; };
|
||||||
|
B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableObject.swift; sourceTree = "<group>"; };
|
||||||
|
B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableUniqueObject.swift; sourceTree = "<group>"; };
|
||||||
B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSProgress+Convenience.swift"; sourceTree = "<group>"; };
|
B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSProgress+Convenience.swift"; sourceTree = "<group>"; };
|
||||||
B5FAD6AB1B51285300714891 /* MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = "<group>"; };
|
B5FAD6AB1B51285300714891 /* MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = "<group>"; };
|
||||||
B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Migration.swift"; sourceTree = "<group>"; };
|
B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Migration.swift"; sourceTree = "<group>"; };
|
||||||
@@ -317,6 +321,8 @@
|
|||||||
B5E834B61B7630BD001D3D50 /* Importing Data */ = {
|
B5E834B61B7630BD001D3D50 /* Importing Data */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */,
|
||||||
|
B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */,
|
||||||
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */,
|
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */,
|
||||||
);
|
);
|
||||||
path = "Importing Data";
|
path = "Importing Data";
|
||||||
@@ -566,6 +572,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */,
|
B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */,
|
||||||
|
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */,
|
||||||
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */,
|
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */,
|
||||||
B5D1E22C19FA9FBC003B2874 /* NSError+CoreStore.swift in Sources */,
|
B5D1E22C19FA9FBC003B2874 /* NSError+CoreStore.swift in Sources */,
|
||||||
B5E84F131AFF847B0064E85B /* Where.swift in Sources */,
|
B5E84F131AFF847B0064E85B /* Where.swift in Sources */,
|
||||||
@@ -584,6 +591,7 @@
|
|||||||
B5E84EE11AFF84500064E85B /* PersistentStoreResult.swift in Sources */,
|
B5E84EE11AFF84500064E85B /* PersistentStoreResult.swift in Sources */,
|
||||||
B5E84F251AFF84860064E85B /* ObjectObserver.swift in Sources */,
|
B5E84F251AFF84860064E85B /* ObjectObserver.swift in Sources */,
|
||||||
B5E84F2F1AFF849C0064E85B /* NotificationObserver.swift in Sources */,
|
B5E84F2F1AFF849C0064E85B /* NotificationObserver.swift in Sources */,
|
||||||
|
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */,
|
||||||
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */,
|
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */,
|
||||||
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */,
|
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */,
|
||||||
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */,
|
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */,
|
||||||
|
|||||||
@@ -27,57 +27,20 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
public protocol ImportableObject: class {
|
// MARK: - BaseDataTransaction
|
||||||
|
|
||||||
typealias ImportSource
|
|
||||||
|
|
||||||
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
|
||||||
|
|
||||||
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
|
||||||
}
|
|
||||||
|
|
||||||
public extension ImportableObject {
|
|
||||||
|
|
||||||
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> 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, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
|
|
||||||
|
|
||||||
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
|
||||||
|
|
||||||
func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public extension ImportableUniqueObject {
|
|
||||||
|
|
||||||
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
|
|
||||||
|
|
||||||
try self.updateFromImportSource(source, inTransaction: transaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public extension BaseDataTransaction {
|
public extension BaseDataTransaction {
|
||||||
|
|
||||||
func importObject<T where T: NSManagedObject, T: ImportableObject>(
|
// MARK: Public
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates an `ImportableObject` by importing from the specified import source.
|
||||||
|
|
||||||
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
|
- parameter source: the object to import values from
|
||||||
|
- returns: the created `ImportableObject` instance
|
||||||
|
*/
|
||||||
|
public func importObject<T where T: NSManagedObject, T: ImportableObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
source: T.ImportSource) throws -> T? {
|
source: T.ImportSource) throws -> T? {
|
||||||
|
|
||||||
@@ -99,7 +62,13 @@ public extension BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
/**
|
||||||
|
Creates multiple `ImportableObject`s by importing from the specified array of import sources.
|
||||||
|
|
||||||
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
|
- parameter sourceArray: the array of objects to import values from
|
||||||
|
*/
|
||||||
|
public func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource]) throws {
|
sourceArray: [T.ImportSource]) throws {
|
||||||
|
|
||||||
@@ -126,10 +95,17 @@ public extension BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
/**
|
||||||
|
Creates multiple `ImportableObject`s by importing from the specified array of import sources.
|
||||||
|
|
||||||
|
- parameter into: an `Into` clause specifying the entity type
|
||||||
|
- parameter sourceArray: the array of objects to import values from
|
||||||
|
- parameter postProcess: a closure that exposes the array of created objects
|
||||||
|
*/
|
||||||
|
public func importObjects<T where T: NSManagedObject, T: ImportableObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource],
|
sourceArray: [T.ImportSource],
|
||||||
postProcess: (sorted: [T]) -> Void) throws {
|
@noescape postProcess: (sorted: [T]) -> Void) throws {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||||
@@ -158,7 +134,7 @@ public extension BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
public func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
source: T.ImportSource) throws -> T? {
|
source: T.ImportSource) throws -> T? {
|
||||||
|
|
||||||
@@ -195,7 +171,7 @@ public extension BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
public func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource],
|
sourceArray: [T.ImportSource],
|
||||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource])? = nil) throws {
|
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource])? = nil) throws {
|
||||||
@@ -262,11 +238,11 @@ public extension BaseDataTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
public func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource],
|
sourceArray: [T.ImportSource],
|
||||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource])? = nil,
|
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource])? = nil,
|
||||||
postProcess: (sorted: [T]) -> Void) throws {
|
@noescape postProcess: (sorted: [T]) -> Void) throws {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||||
|
|||||||
84
CoreStore/Importing Data/ImportableObject.swift
Normal file
84
CoreStore/Importing Data/ImportableObject.swift
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// ImportableObject.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
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ImportableObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
`NSManagedObject` subclasses that conform to the `ImportableObject` protocol can be imported from a specified `ImportSource`. This allows transactions to create and insert instances this way:
|
||||||
|
|
||||||
|
class MyPersonEntity: NSManagedObject, ImportableObject {
|
||||||
|
typealias ImportSource = NSDictionary
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||||
|
let json: NSDictionary = // ...
|
||||||
|
let person = try! transaction.importObject(
|
||||||
|
Into(MyPersonEntity),
|
||||||
|
source: json
|
||||||
|
)
|
||||||
|
// ...
|
||||||
|
transaction.commit()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
public protocol ImportableObject: class {
|
||||||
|
|
||||||
|
/**
|
||||||
|
The data type for the import source. This is most commonly an `NSDictionary` or another external source such as an `NSUserDefaults`.
|
||||||
|
*/
|
||||||
|
typealias ImportSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
|
||||||
|
*/
|
||||||
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implements the actual importing of data from `source`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importObjects(:sourceArray:)` call to be cancelled.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
*/
|
||||||
|
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ImportableObject (Default Implementations)
|
||||||
|
|
||||||
|
public extension ImportableObject {
|
||||||
|
|
||||||
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
136
CoreStore/Importing Data/ImportableUniqueObject.swift
Normal file
136
CoreStore/Importing Data/ImportableUniqueObject.swift
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// ImportableUniqueObject.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
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ImportableUniqueObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
`NSManagedObject` subclasses that conform to the `ImportableUniqueObject` protocol can be imported from a specified `ImportSource`. This allows transactions to either update existing objects or create new instances this way:
|
||||||
|
|
||||||
|
class MyPersonEntity: NSManagedObject, ImportableUniqueObject {
|
||||||
|
typealias ImportSource = NSDictionary
|
||||||
|
typealias UniqueIDType = NSString
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||||
|
let json: NSDictionary = // ...
|
||||||
|
let person = try! transaction.importUniqueObject(
|
||||||
|
Into(MyPersonEntity),
|
||||||
|
source: json
|
||||||
|
)
|
||||||
|
// ...
|
||||||
|
transaction.commit()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
public protocol ImportableUniqueObject: ImportableObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
The data type for the import source. This is most commonly an `NSDictionary` or another external source such as an `NSUserDefaults`.
|
||||||
|
*/
|
||||||
|
typealias ImportSource
|
||||||
|
|
||||||
|
/**
|
||||||
|
The data type for the entity's unique ID attribute
|
||||||
|
*/
|
||||||
|
typealias UniqueIDType: NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
The keyPath to the entity's unique ID attribute
|
||||||
|
*/
|
||||||
|
static var uniqueIDKeyPath: String { get }
|
||||||
|
|
||||||
|
/**
|
||||||
|
The object's unique ID value
|
||||||
|
*/
|
||||||
|
var uniqueIDValue: UniqueIDType { get set }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns the value returned by the `shouldUpdateFromImportSource(:inTransaction:)` implementation.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
|
||||||
|
*/
|
||||||
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return `true` if an object should be updated from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
- returns: `true` if an object should be updated from `source`. Return `false` to ignore.
|
||||||
|
*/
|
||||||
|
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the unique ID as extracted from `source`. This method is called before `shouldInsertFromImportSource(...)` or `shouldUpdateFromImportSource(...)`. Return `nil` to skip importing from `source`. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
- returns: the unique ID as extracted from `source`, or `nil` to skip importing from `source`.
|
||||||
|
*/
|
||||||
|
static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implements the actual importing of data from `source`. This method is called just after the object is created and assigned its unique ID as returned from `uniqueIDFromImportSource(...)`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. The default implementation simply calls `updateFromImportSource(...)`.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
*/
|
||||||
|
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implements the actual importing of data from `source`. This method is called just after the existing object is fetched using its unique ID. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
|
||||||
|
|
||||||
|
- parameter source: the object to import from
|
||||||
|
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
|
||||||
|
*/
|
||||||
|
func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ImportableUniqueObject (Default Implementations)
|
||||||
|
|
||||||
|
public extension ImportableUniqueObject {
|
||||||
|
|
||||||
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
|
return self.shouldUpdateFromImportSource(source, inTransaction: transaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
|
||||||
|
|
||||||
|
try self.updateFromImportSource(source, inTransaction: transaction)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,18 +111,15 @@ internal extension NSManagedObjectContext {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void)?) {
|
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void) = { _ in }) {
|
||||||
|
|
||||||
self.performBlock { () -> Void in
|
self.performBlock { () -> Void in
|
||||||
|
|
||||||
guard self.hasChanges else {
|
guard self.hasChanges else {
|
||||||
|
|
||||||
if let completion = completion {
|
GCDQueue.Main.async {
|
||||||
|
|
||||||
GCDQueue.Main.async {
|
completion(result: SaveResult(hasChanges: false))
|
||||||
|
|
||||||
completion(result: SaveResult(hasChanges: false))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -138,12 +135,9 @@ internal extension NSManagedObjectContext {
|
|||||||
saveError,
|
saveError,
|
||||||
"Failed to save \(typeName(NSManagedObjectContext))."
|
"Failed to save \(typeName(NSManagedObjectContext))."
|
||||||
)
|
)
|
||||||
if let completion = completion {
|
GCDQueue.Main.async {
|
||||||
|
|
||||||
GCDQueue.Main.async {
|
completion(result: SaveResult(saveError))
|
||||||
|
|
||||||
completion(result: SaveResult(saveError))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -152,7 +146,7 @@ internal extension NSManagedObjectContext {
|
|||||||
|
|
||||||
parentContext.saveAsynchronouslyWithCompletion(completion)
|
parentContext.saveAsynchronouslyWithCompletion(completion)
|
||||||
}
|
}
|
||||||
else if let completion = completion {
|
else {
|
||||||
|
|
||||||
GCDQueue.Main.async {
|
GCDQueue.Main.async {
|
||||||
|
|
||||||
|
|||||||
@@ -990,6 +990,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
|||||||
)
|
)
|
||||||
|
|
||||||
case .Move:
|
case .Move:
|
||||||
|
CoreStore.log(.Notice, message: "\(indexPath!) - \(newIndexPath!)")
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||||
ListMonitorDidMoveObjectNotification,
|
ListMonitorDidMoveObjectNotification,
|
||||||
object: self,
|
object: self,
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ public protocol ListObserver: class {
|
|||||||
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>)
|
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ListObserver (Default Implementations)
|
||||||
|
|
||||||
public extension ListObserver {
|
public extension ListObserver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,6 +152,9 @@ public protocol ListObjectObserver: ListObserver {
|
|||||||
func listMonitor(monitor: ListMonitor<ListEntityType>, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
|
func listMonitor(monitor: ListMonitor<ListEntityType>, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ListObjectObserver (Default Implementations)
|
||||||
|
|
||||||
public extension ListObjectObserver {
|
public extension ListObjectObserver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,6 +212,9 @@ public protocol ListSectionObserver: ListObjectObserver {
|
|||||||
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ListSectionObserver (Default Implementations)
|
||||||
|
|
||||||
public extension ListSectionObserver {
|
public extension ListSectionObserver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ public protocol ObjectObserver: class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ObjectObserver (Default Implementations)
|
||||||
|
|
||||||
public extension ObjectObserver {
|
public extension ObjectObserver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ let person = transaction.create(Into(MyPersonEntity))
|
|||||||
|
|
||||||
For cases where multiple `NSPersistentStore`s contain the same entity, the destination configuration's name needs to be specified as well:
|
For cases where multiple `NSPersistentStore`s contain the same entity, the destination configuration's name needs to be specified as well:
|
||||||
|
|
||||||
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
|
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
|
||||||
|
|
||||||
This helps the `NSManagedObjectContext` to determine which
|
This helps the `NSManagedObjectContext` to determine which
|
||||||
*/
|
*/
|
||||||
@@ -48,7 +48,7 @@ public struct Into<T: NSManagedObject> {
|
|||||||
Initializes an `Into` clause.
|
Initializes an `Into` clause.
|
||||||
Sample Usage:
|
Sample Usage:
|
||||||
|
|
||||||
let person = transaction.create(Into<MyPersonEntity>())
|
let person = transaction.create(Into<MyPersonEntity>())
|
||||||
*/
|
*/
|
||||||
public init(){
|
public init(){
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user