Six Common Questions About Core Data

Six Common Questions About Core Data

Core Data has been around for more than a decade and it has grown into a robust persistence solution. I have used Core Data in dozens of applications and enjoy working with the framework. Some developers swear by Core Data while others passionately dislike it.

I have been teaching developers how to use the Core Data framework for more than ten years and that has taught me that most of the negative feedback I see about the framework is a result of misunderstanding the framework and skipping the basics. In this post, I would like to answer a number of common questions about Core Data.

1 Is Core Data Available on All Devices

Core Data originated on the desktop. The framework was introduced alongside the release of Mac OS X Tiger in 2005. Apple brought Core Data to iOS with the release of iPhone SDK 3.0. Today, the Core Data framework is available on iOS, tvOS, macOS, iPadOS, watchOS, and Mac Catalyst. This means that you can use the same persistence solution across Apple's platforms.

There is one caveat, though. Using Core Data on tvOS is possible, but you shouldn't use Core Data for persisting data. What does that mean? Apple clearly states that there is no persistent local storage for application on tvOS. What that means in practice is that the data you write to disk can be purged at any time. This won't happen while your application is in the foreground, but it can happen that the data you wrote to disk was deleted by the system the next time your application is launched. Keep that in mind.

2 Is Core Data Encrypted

Does Core Data encrypt the persistent store it manages? The answer is yes and no. Core Data doesn't encrypt the data you store in the persistent store, but it is possible to enable encryption. Let me explain what that means and how it works.

Enabling encryption is easy to add. You can add a persistent store to the persistent store coordinator by invoking the addPersistentStore(ofType:configurationName:at:options:) method. In this example, the application adds a persistent store, a SQLite database, to the persistent store coordinator. The third argument of addPersistentStore(ofType:configurationName:at:options:), persistentStoreURL, defines the location of the persistent store. This should look familiar.

do {
    // Add Persistent Store
    try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType,
                                                      configurationName: nil,
                                                      at: persistentStoreURL,
                                                      options: nil)
} catch {
    // Error Handling
    ...
}

To enable encryption, you need to pass a dictionary of options as the last argument of addPersistentStore(ofType:configurationName:at:options:). You need to set a value for key NSPersistentStoreFileProtectionKey. The possible options are:

  • complete: This is the most strict form of protection. The persistent store cannot be read from or written to if (1) the device is locked or (2) when the device is booting.
  • completeUnlessOpen: This option is less strict. As the name implies, the file is stored in an encrypted format from the moment it is no longer open.
  • completeUntilFirstUserAuthentication: This option offers basic protection. It simply means that the file is encrypted until the device has booted. If you power down your device, the persistent store is stored on disk in an encrypted format. This is the default option as of iOS 5.0.
  • none: It is possible to disable encryption entirely by setting the value for the NSPersistentStoreFileProtectionKey key to none. This isn't recommended, though. The vast majority of applications should, as a minimum, stick with the default option, that is, completeUntilFirstUserAuthentication.
do {
    // Define Options
    let options: [AnyHashable: Any] = [
        NSPersistentStoreFileProtectionKey: FileProtectionType.complete
    ]

    // Add Persistent Store
    try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType,
                                                      configurationName: nil,
                                                      at: persistentStoreURL,
                                                      options: options)
} catch {
    // Error Handling
    ...
}

3 Is Core Data Safe/Secure

This question is closely related to the previous question. As a developer, you decide how safe or secure the data your application stores in the persistent store is. You do this by defining the file protection type of the persistent store.

4 Is Core Data a Relational Database

This question keeps popping up time and time again and it's a good question if you are new to Core Data. What you need to know is that Core Data is not a database. That said, when working with Core Data it acts as a relational database hence the confusion.

Core Data is a persistence solution for Apple's platforms and it supports several types of persistent stores, including SQLite. The framework provides an API for interacting with one or more persistent stores.

Managing relationships is a key feature of the Core Data framework and it offers a powerful API for working with relational data. Does this mean Core Data is a relational database? No, but if you need such a solution then Core Data is a very good choice.

5 Is Core Data Slow

If Core Data is slow, then you are most likely (1) using a very big data set or (2) not correctly using the framework. The latter is the most common issue. Core Data was designed with speed and efficiency in mind. It only fetches the data your application needs and fills in the gaps as your application asks for more data.

Unless you are working with a very big data set, I wouldn't worry about performance. Should you run into performance issues, then it's time to take a close look at how your application is using the framework.

6 Is Core Data Thread Safe

Is Core Data thread safe? Yes and no. Even though the framework originated in a time where computers with multicore processors were rare, Core Data is designed to operate in a multithreaded environment. In other words, it works fine on the latest iPhone and a Mac Pro with 28 cores.

But you need to know the rules Core Data plays by. A managed object context is always bound to a dispatch queue, a queue for short. The same applies to managed objects. You should never pass a managed object from one queue to another. If you need to access a managed object from another queue, then pass the ID of the managed object, an instance of the NSManagedObjectID class. A NSManagedObjectID instance uniquely identifies a record in the persistent store. Working In a Multithreaded Environment covers Core Data and threading in more detail.