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 more

    Declaration

    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 and NSAsynchronousFetchRequest 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 via NSNotification.

    Declaration

    Swift

    public private(set) lazy var mainQueueContext: NSManagedObjectContext =
  • Creates a SQLite backed Core Data stack for a given model in the supplied NSBundle.

    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‘s addPersistentStoreWithType

    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‘s addPersistentStoreWithType

    Declaration

    Swift

    public static func constructInMemoryStack(model: NSManagedObjectModel) throws -> CoreDataStack
  • Result containing either an instance of NSPersistentStoreCoordinator or ErrorType

    See more

    Declaration

    Swift

    public enum CoordinatorResult
  • Result containing either an instance of NSManagedObjectContext or ErrorType

    See more

    Declaration

    Swift

    public enum BatchContextResult
  • Result containing either an instance of CoreDataStack or ErrorType

    See more

    Declaration

    Swift

    public enum SetupResult
  • Result of void representing success or an instance of ErrorType

    See more

    Declaration

    Swift

    public enum SuccessResult
  • This function resets the NSPersistentStore connected to the NSPersistentStoreCoordinator. For SQLite based stacks, this function will also remove the SQLite 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 via NSNotification observing.

    Declaration

    Swift

    public func newChildContext(type: NSManagedObjectContextConcurrencyType = .privateQueueConcurrencyType,
                                    name: String? = "Main Queue Context Child") -> NSManagedObjectContext
  • Creates a new background NSManagedObjectContext connected to a discrete NSPersistentStoreCoordinator 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)