CoreDataStack
public final class CoreDataStack
Three layer Core Data stack comprised of:
- A primary background queue context with an
NSPersistentStoreCoordinator
- A main queue context that is a child of the primary queue
- A method for spawning many background worker contexts that are children of the main queue context
Calling save()
on any NSMangedObjectContext
belonging to the stack will automatically bubble the changes all the way to the NSPersistentStore
Constructing Your Stack
Import Framework
via: Carthage
import CoreDataStack
or via CocoaPods
import BNRCoreDataStack
Standard SQLite Backed
CoreDataStack.constructSQLiteStack(withModelName: TestModel
) { result in
switch result {
case .success(let stack):
self.myCoreDataStack = stack
print(Success
)
case .failure(let error):
print(error)
}
}
In-Memory Only
do {
myCoreDataStack = try CoreDataStack.constructInMemoryStack(
withModelName: TestModel
)
} catch {
print(error)
}
Working with Managed Object Contexts
Private Persisting/Coordinator Connected Context
This is the root level context with a PrivateQueueConcurrencyType
for asynchronous saving to the NSPersistentStore
.
Fetching, Inserting, Deleting or Updating managed objects
should occur on a child of this context rather than directly.
myCoreDataStack.privateQueueContext
Main Queue / UI Layer Context
This is our MainQueueConcurrencyType
context
with its parent being the private persisting context.
This context should be used for any main queue or UI related tasks.
Examples include setting up an NSFetchedResultsController
,
performing quick fetches, making UI related updates like a bookmark
or favoriting an object.
Performing a save() call on this context will automatically trigger a save on its parent via NSNotification
.
myCoreDataStack.mainQueueContext
Creating a Worker Context
Calling newChildContext()
will vend us a PrivateQueueConcurrencyType
child context of the main queue context.
Useful for any longer running task, such as inserting or updating data from a web service.
Calling save() on this managed object context will automatically trigger a save
on its parent context via NSNotification
.
let workerContext = myCoreDataStack.newChildContext()
workerContext.performBlock() {
// fetch data from web-service
// update local data
workerContext.saveContext()
}
Large Import Operation Context
In most cases, offloading your longer running work to a background worker context will be sufficient in alleviating performance woes. If you find yourself inserting or updating thousands of objects, then perhaps opting for a standalone managed object context with a discrete persistent store would be the best option, like so:
myCoreDataStack.newBatchOperationContext() { result in
switch result {
case .success(let batchContext):
// my big import operation
case let .failure(error):
print(error)
}
}
Resetting The Stack
At times it can be necessary to completely reset your Core Data store
and remove the file from disk,
for example, when a user logs out of your application.
An instance of CoreDataStack
can be reset by using the function
resetStore(resetCallback: CoreDataStackStoreResetCallback)
:
myCoreDataStack.resetStore() { result in
switch result {
case .success:
// proceed with fresh Core Data Stack
case let .failure(error):
print(error)
}
}
-
CoreDataStack specific ErrorTypes
See moreDeclaration
Swift
public enum Error: Swift.Error
-
Primary persisting background managed object context. This is the top level context that possess an
NSPersistentStoreCoordinator
and saves changes to disk on a background queue.Fetching, Inserting, Deleting or Updating managed objects should occur on a child of this context rather than directly.
note:
NSBatchUpdateRequest
andNSAsynchronousFetchRequest
require a context with a persistent store connected directly.Declaration
Swift
public private(set) lazy var privateQueueContext: NSManagedObjectContext =
-
The main queue context for any work that will be performed on the main queue. Its parent context is the primary private queue context that persist the data to disk. Making a
save()
call on this context will automatically trigger a save on its parent viaNSNotification
.Declaration
Swift
public private(set) lazy var mainQueueContext: NSManagedObjectContext =
-
Creates a
SQLite
backed Core Data stack for a given model in the suppliedNSBundle
.Declaration
Swift
public static func constructSQLiteStack(modelName: String, in bundle: Bundle = Bundle.main, at desiredStoreURL: URL? = nil, persistentStoreOptions: [AnyHashable : Any]? = NSPersistentStoreCoordinator.stockSQLiteStoreOptions, on callbackQueue: DispatchQueue? = nil, callback: @escaping SetupCallback)
-
Creates a
SQLite
backed Core Data stack for a given model.Declaration
Swift
public static func constructSQLiteStack(model: NSManagedObjectModel, at desiredStoreURL: URL? = nil, persistentStoreOptions: [AnyHashable : Any]? = NSPersistentStoreCoordinator.stockSQLiteStoreOptions, on callbackQueue: DispatchQueue? = nil, callback: @escaping SetupCallback)
-
Creates an in-memory Core Data stack for a given model in the supplied
NSBundle
.This stack is configured with the same concurrency and persistence model as the
SQLite
stack, but everything is in-memory.Throws
Any error produced from
NSPersistentStoreCoordinator
‘saddPersistentStoreWithType
Declaration
Swift
public static func constructInMemoryStack(modelName: String, in bundle: Bundle = Bundle.main) throws -> CoreDataStack
-
Creates an in-memory Core Data stack for a given model.
This stack is configured with the same concurrency and persistence model as the
SQLite
stack, but everything is in-memory.Throws
Any error produced from
NSPersistentStoreCoordinator
‘saddPersistentStoreWithType
Declaration
Swift
public static func constructInMemoryStack(model: NSManagedObjectModel) throws -> CoreDataStack
-
Result containing either an instance of
See moreNSPersistentStoreCoordinator
orErrorType
Declaration
Swift
public enum CoordinatorResult
-
Result containing either an instance of
See moreNSManagedObjectContext
orErrorType
Declaration
Swift
public enum BatchContextResult
-
Result containing either an instance of
See moreCoreDataStack
orErrorType
Declaration
Swift
public enum SetupResult
-
Result of void representing
See moresuccess
or an instance ofErrorType
Declaration
Swift
public enum SuccessResult
-
This function resets the
NSPersistentStore
connected to theNSPersistentStoreCoordinator
. ForSQLite
based stacks, this function will also remove theSQLite
store from disk.Declaration
Swift
public func resetStore(with persistentStoreOptions: [AnyHashable: Any]? = NSPersistentStoreCoordinator.stockSQLiteStoreOptions, on callbackQueue: DispatchQueue? = nil, callback: @escaping StoreResetCallback)
-
Returns a new
NSManagedObjectContext
as a child of the main queue context.Calling
save()
on this managed object context will automatically trigger a save on its parent context viaNSNotification
observing.Declaration
Swift
public func newChildContext(type: NSManagedObjectContextConcurrencyType = .privateQueueConcurrencyType, name: String? = "Main Queue Context Child") -> NSManagedObjectContext
-
Creates a new background
NSManagedObjectContext
connected to a discreteNSPersistentStoreCoordinator
created with the same store used by the stack in construction.Declaration
Swift
public func newBatchOperationContext(with persistentStoreOptions: [AnyHashable: Any]? = NSPersistentStoreCoordinator.stockSQLiteStoreOptions, on callbackQueue: DispatchQueue? = nil, callback: @escaping BatchContextCallback)