Setting up Mogenerator in Xcode 4.5

Dec 3, 2012 00:00 · 740 words · 4 minute read

Mogenerator is a command-line utility that helps manage NSManagedObject classes by generating two sets of files - machine files, which represent the Core Data entities as NSManagedObject subclasses; and human files, which you can use for custom edits.

Without Mogenerator, changing the Core Data model will overwrite the NSManagedObject subclasses and you stand to lose any custom changes you’ve made. With Mogenerator, those changes are kept separate and won’t be overwritten.

There isn’t a whole lot of documentation about setting up Mogenerator, so this is a quick write-up of my process. It assumes that you’ve already created a project with Core Data installed, and you’ve created a Data Model.

First, you’ll need to download and install Mogenerator from http://rentzsch.github.com/mogenerator/. You can install from a .dmg, or use Homebrew.

Next, set up your project’s file structure ready for the new files that will be generated. Where you put them is up to you, but I tend to use this kind of structure:

Foo/
     |
     |- Foo.xcodeproj
     |
     |- Foo/
     |   |
     |   |-  en.lproj
     |   |    FooAppDelegate.h
     |   |    FooAppDelegate.m
     |   |    ViewController.h
     |   |    ViewController.m
     |   |      etc
     |   |
     |   |-  CoreData/
     |          |
     |          |- Human
     |          |   |
     |          |   |- <editable files will go here>
     |          |
     |          |- Machine/
     |              |
     |              |- <system files will go here>
     |
     |- FooTests/
         |
         |- etc

Now set up your project to use Mogenerator: Switch to the project’s Summary page by selecting the blue Project icon at the top of the app’s folder heirarchy. In the second column, you should see the list of targets. Add an Aggregate target by clicking the

Add Target icon at the bottom of the list, and selecting the Aggregate target from the template chooser. Call your new Aggregate target Mogenerator or something similar (the name isn’t significant)

Select the new Mogenerator target and click the Add Build Phase icon at the bottom right - from the pop-up list, select the Add Run Script option

Open up the Run Script section, and edit the script that’s shown.

    cd Foo
    /usr/local/bin/mogenerator --template-var arc=true
    -m Foo.xcdatamodeld/Foo.xcdatamodel/ -M CoreData/Machine/ -H CoreData/Human/

(the mogenerator command should be on one line - I’ve split it here so that it’s visible)

Replace Foo with your app’s name. This script does several things:

  • it switches from the project’s root directory to the app subdirectory
  • it runs Mogenerator (you may not need the full path to the mogenerator app, but if the script fails with a file not found error, this is the workaround)
  • it generates files which will work with ARC (if you’re not using ARC, remove the --template-var arc=true switch)
  • it uses the Foo.xcdatamodeld/Foo.xcdatamodel file as the basis of the model files that it will generate
  • it places the editable human-readable files in the CoreData/Human directory
  • it places the non-editable machine files in the CoreData/Machine directory Now switch to your app’s main target, and add a target dependency - from the menu that pops up, select the newly-created Mogenerator target.

UPDATE I recently came across a neat trick for managing build scripts which makes keeping them under source control a little easier. Rather than putting the script directly into the Xcode settings, you instead create a standalone script in the project folder and then run this from the Run Script section. See the post here.

Finally, select your main target (e.g. ‘Foo’), and open the ‘Build Phases’ tab again. At the top of the section, you’ll see Target Dependencies. Click the + icon below this, and then select your newly-created Aggregate target. This will force the mogenerator script to be run on every build.

At this point, you’re ready to start using Mogenerator. There’s a simple process that you’ll need to follow from here on in to make sure that the Mogenerated files are created correctly

  • When you create a new managed entity, change its class so that Mogenerator will do its stuff. Say you call the new entity Thing - then you’ll need to change its class from NSManagedObject to Thing.
  • build the project
  • locate the files that have been created in the Human and Machine subdirectories and drag them into your project. You’ll find four in total - Thing.h, Thing.m, _Thing.h and _Thing.m. Don’t touch the underscored files - those are the machine-generated ones.

Any subsequent changes in the Thing entity will be automatically reflected in the class files once they’ve been included into the project.