Episode #238

Core Data in iOS 10

28 minutes
Published on October 4, 2016

This video is only available to subscribers. Get access to this video and 572 others.

iOS 10 brings some welcome improvements to Core Data, including the all new NSPersistentContainer class. With this release, Apple has created a streamlined API that captures the most common uses of Core Data in iOS applications. In this episode we'll take a look at NSPersistentContainer, as well as the new code-generation capability in Xcode 8.

Episode Links

NSPersistentContainer

let container = NSPersistentContainer(name: "Episodes")

container.loadPersistentStores { (storeDescription, error) in

    container.viewContext.automaticallyMergesChangesFromParent = true
    try! container.viewContext.setQueryGenerationFrom(.current)

    if let e = error {
        print("Error: \(e)")
    } else {
        print("Core data loaded: \(storeDescription)")
    }
}

Fetching Existing Records

Generated models now produced strongly typed fetch requests:

let fetchRequest: NSFetchRequest<Episode> = Episode.fetchRequest()
let existingEpisodes = try! fetchRequest.execute()
let existingEpisodeLookup = existingEpisodes.reduce([:], { (lookup, episode) -> [Int:Episode] in
    var mutableLookup = lookup
    mutableLookup[Int(episode.id)] = episode
    return mutableLookup
})

Insert or Update Records in the Background

container?.performBackgroundTask { moc in
   episodes.forEach { jsonEpisode in
       let model = existingEpisodeLookup[jsonEpisode.id] ?? Episode(context: moc)
       model.id = Int32(jsonEpisode.id)
       model.title = jsonEpisode.title
       model.summary = jsonEpisode.summary
       model.thumbnailURLValue = jsonEpisode.thumbnailURLValue
   }

   try! moc.save()
}

Merging Changes Automatically

First, we set our view context to merge changes from the store, and pin changes to .current to always see the latest data.

container.viewContext.automaticallyMergesChangesFromParent = true
try! container.viewContext.setQueryGenerationFrom(.current)

When the save happens on another context, it gets performed on the store, which will merge changes on the view context. Our fetched results controller detects this change and notifies its delegate:


extension ViewController : NSFetchedResultsControllerDelegate {
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        loadFromCoreData()
    }
}

This episode uses Ios 10.0, Xcode 8.0.