Core Data WWDC 2020 FAQ

Hi folks

I hope this has been an exciting and informative week for everyone. I'm sorry we weren't all able to meet up personally in the labs this year.

Unfortunately we also weren't able to schedule time for everyone who requested a lab session. To make the best use of time, I've pulled together some common questions.
  • CloudKit Sharing with Core Data

The Core Data CK mirroring does not support sharing at this time.
  • Xcode 12's new SwiftUI project template

There is a known issue where the Core Data checkbox is not enabled if you make a new SwiftUI life cycle project. You can of course add Core Data to a SwiftUI project
  • Forcing CloudKit to sync immediately

We don't facilitate a synchronous forced import / export. Please file bug reports aggressively so we can determine if there was an issue with the sandbox environment, configuration, push notifications, or your operation not getting the priority it deserved, etc.
  • CloudKit syncing progress

New in iOS 14 and macOS 11 are NSPersistentCloudKitContainerEvent and NSPersistentCloudKitContainerEventRequest. Please see our WWDC session. They function similarly to persistent history.
  • Core Data CloudKit on macOS Catalyst crashes in Xcode debugger

On macOS 10.15, Catalyst apps would crash if a debugger was attached to the process while performing CloudKit operations. This is fixed in your developer seed of macOS 11.
  • Set vs NSSet in Swift accessor methods

Set in Swift is an immutable value type. We do not recommend making Core Data relationships typed this way despite the obvious convenience. Core Data makes heavy use of Futures, especially for relationship values. These are reference types expressed as NSSet. The concrete instance is a future subclass however. This lets us optimize memory and performance across your object graph. Declaring an accessor as Set forces an immediate copy of the entire relationship so it can be an immutable Swift Set. This loads the entire relationship up front and fulfills the Future all the time, immediately. You probably do not want that.
Similarly for fetch requests with batching enabled, you do not want a Swift Array but instead an NSArray to avoid making an immediate copy of the future.
  • Schema migration & performance

You should basically only use lightweight migration with an inferred mapping model. You should avoid your own custom mapping models and migration managers as these require an unbounded amount of memory. You can chain migrations together by avoiding NSMigratePersistentStoresAutomaticallyOption and checking for NSPersistentStoreIncompatibleVersionHashError from addPersistentStore. The store metadata can drive your decision about a migration to perform and you can migrate to an intermediate schema and massage the data in code. When ready you make a second migration to your final (the current app) schema.

Additionally you should almost never use NSPersistentStoreCoordinator's migratePersistentStore... method but instead use the newer replacePersistentStoreAtURL.. (you can replace emptiness to make a copy). The former loads the store into memory so you can do fairly radical things like write it out as a different store type. It pre-dates iOS. The latter will perform an APFS clone where possible.


Feedback Assistant will eventually route to us if you categorize the issue as Core Data.

Hope to see you all next year.

Answers

Set in Swift is an immutable value type. We do not recommend making Core Data relationships typed this way despite the obvious convenience. Core Data makes heavy use of Futures, especially for relationship values. These are reference types expressed as NSSet. The concrete instance is a future subclass however. This lets us optimize memory and performance across your object graph. Declaring an accessor as Set forces an immediate copy of the entire relationship so it can be an immutable Swift Set. This loads the entire relationship up front and fulfills the Future all the time, immediately. You probably do not want that.

In my opinion, it is unfortunate this is "documented" here. The internet is full of guidance counter to this and to have it hidden as a post in a developer forum is sub-optimal. I stumbled upon this guidance by accident while looking for something else.

More over, if this really is true the idea that a better "batteries included" reference type that conforms to Swift's Collection is not provided in Core Data this many years after Swift came on the scene is unfortunate especially since Core Data is Apple's hallmark framework for application developers who desire to persist their users' data in a robust and feature-rich way.