Core Data

Core Data Programming Guide

Setting up

Apple’s documentation seems to be fine.

Persistent Store types are here, you’ll mostly be using NSSQLStoreType or NSInMemoryStoreType (for testing).

Concurrency

NSManagedObjectContext is the way to read/write objects to/from core data. Create a managed object context with a given concurrency type (either mainQueueConcurrencyType or privateQueueConcurrencyType), and only operate on it within blocks passed to perform(_:) or performAndWait(_:) calls. Be sure to only have one managed object context for your persistent store coordinator, or you’ll encounter strange crashes.

Additionally, keep in mind that NSManagedObject subclasses are not thread-safe (there are only a handful of properties/methods that are safe to access outside of a perform(_:) or performAndWait(_:) call). Instead of passing instances of NSManagedObject, pass around the object’s NSManagedObjectID (obtained from the managed object’s objectID property.

My preferred approach for accessing core data is to convert the NSManagedObject instance into another, thread-safe model object. This has the advantage of not leaking implementation details and concerns about my database layer to other layers of my app. Which, in addition to being good design, also means that I can switch out (or ignore) databases as makes sense for what I’m trying to do.

Storing Records

In my experience, using MyNSManagedObjectSubclass(managedObjectContext: context); context.insert(myCreatedObject) doesn’t work. Instead, use the older NSEntityDescription.insertNewObject(forEntityName:into:) to create and insert new objects.

Fetch Requests

Fetching by property with type URI

I ran into issues figuring this out. The approach you want is:

fetchRequest.predicate = NSPredicate("url.absoluteString = %@", urlToFetch.absoluteString)

Errors

Multiple NSEntityDescriptions claim an NSManagedObjectContext subclass

I encountered this in tests, where I was initiating up the Core Data stack from scratch with each test. Turns out that, because CoreData creates new classes when you bring up the context, you’ll end up seeing this warning with every new test.

The solution is to not create so many ManagedObjectModels - that is, instead of bringing up a new stack with each test, bring it up once, and then delete every object between run.