Monday, June 27, 2011

Versioning Core Data Models and Unit Testing with Xcode 4

Today at my day job I got to create a new version of a Core Data model. The Good News: automatic migration really does Just Work in the simple case of adding a new attribute (column) to an entity (table). The Bad News: Unit Tests do not necessarily automatically get the new version of the model.

For reference, I'm using Xcode 4.0.2, build 4A2002a. Also using Google Toolbox for Mac and OCMock for unit testing.

For some reason, my unit test target (we're using Google Toolbox for Mac and OCMock for unit testing) was originally set up with the following files targeted for various build phases:

  • Compile Sources: MyModel.xcdatamodel (the original version, underneath the .xcdatamodeld directory)
  • Copy Bundle Resources: no model

After creating the new version of the data model, we really want the .xcdatamodeld (the whole directory structure that knows about all versions) to be what gets compiled / bundled.

  • Compile Sources: MyModel.xcdatamodeld
  • Copy Bundle Resources: MyModel.xcdatamodeld

So I had to delete MyModel.xcdatamodel from the Compile Sources build phase and add MyModel.xcdatamodeld. The really weird thing was I could not get Xcode to add the file using the add dialog in the "Choose items to add" dialog that the plus sign brings up.

Note: to see the "Choose items to add" dialog I'm referring to in Xcode 4, do this:

  • Click on the Project name in the Project navigator
  • Click on a Target
  • Click on "Build Phases" at the top of the project info section
  • Expand the "Compile Sources" phase
  • Scroll to the bottom of "Compile Sources" and click on the "plus" sign (+)

Using this dialog, Xcode will allow you to select any of the .xcdatamodel files, but not the .xcdatamodeld. The only way I could get the .xcdatamodeld file in "Compile Sources" (and "Copy Bundle Resources") was by clicking on the file in the Project navigator and dragging it into the build phase. Then it worked like a charm.

One other bit of weirdness: A lot of blogs that talk about versioning Core Data models don't mention how to set the selected version in Xcode 4. To do this:

  • Select the .xcdatamodeld file in the Project navigator
  • Open the Utilities pane (in the upper right corner of Xcode; see image)
  • Select the current version from the Versioned Data Model section of the File Inspector (see image)


Final note: The app pictured in the images, TripCents, is not my current client's app; it's one of mine.