Projects

PmWiki

edit SideBar

bleep. open source wiki

Core Data, NSTreeController? & NSOutlineView?

Core Data is one of the more powerful APIs? Apple has to offer, when tied to Cocoa Bindings, it becomes much more powerful, and available to amateurs and some pros alike.

Sounds great right? There's a catch (there's always a catch, you should know that by now). Cocoa Bindings, while powerful, are one of the more difficult mechanisms to work within Cocoa-land. The interface you use to interact with them is about as counter-intuitive as if Copy's keyboard shortcut was Apple+Alt+Shift+F5+C. Another unfortunate catch, is that, the Apple Documentation Team seems to have forgotten, or never heard of Cocoa Bindings, so past a few tutorials here and there, we're pretty much on our own.

Binding an NSTableView? is easy, but what about avoiding writing an NSOutlineView? data source? Cocoa Bindings can do that to! :)

First things first, we need a good Core Data Application Project (a good fresh start never hurt anybody). Inside Xcode, just go to File>New Project, and then select the "Core Data Application", name your project, and you're on your way.

From here, we can go on to create our Core Data - Data Model...

Cocoa Bindings, as well as Core Data, tend to be quite picky about naming, so choose wisely; here's mine

Honestly, it's a bit simple, but not obvious right away. Firstly, "entityTitle" is a simple, non-optional, String attribute. Meanwhile, TopLevelEntity?'s "children" relationship is a To-many (i.e. can point to multiple entity objects) inverse relationship with SecondLevelEntity? (the inverse relationship being between TopLevelEntity?.children <-->> SecondLevelEntity?.parent )

Logically, this means that for each data object of type TopLevelEntity?, it can relate to an infinite (more or less) number of SecondLevelEntitys? via it's "children" relationship. Meanwhile, each data object of type SecondLevelEntity? can have only one "parent" entity via it's "parent" relationship (pointing to a TopLevelEntity?), and <b>zero</b> "children" (since that is a dead relationship, it's merely there to return nil)

SecondLevelEntity?'s "children" relationship is optional, and "transient," meaning it is not something that will stick around in the Core Data store.

Now we can set up our interface, and given that this is very simple, we'll set up two window's to add data to the data store (make sure you check "VIsible? At Launch Time" for both windows!), as well as to display our nice NSOutlineView? (which will be bound to an NSTreeController?)

Doing this is remarkably easy, using some features of Core Data. Inside Interface Builder, create a few windows, preferably one for each entity (in addition to the main window) Then click into your XCode? Core Data Object Model Window, and Alt+Drag your entity into one of your windows, Interface Builder will then prompt you if you want to create a one, or many interface for the dragged entity, choose "Many Objects", and repeat for the other entity. After you have done this, you should have two nice sets of interfaces, in your last window, the original main window, drop an NSOutlineView? control into it. More or less, your finished product should look something like this.

Now that these are bound correclty, since Interface Builder does this all <i>automagically</i> for us, we can create our NSTreeController?, which you can drag from the "Controllers" palette in Interface Builder.

Open up inspector while the NSTreeController? is selected, and set it's attributes as such:

You will then have to set that NSTreeController?'s managedObjectContext via Cocoa Bindings to your pre-generated App_Delegate class (think of the managedObjectContext as the link between your data, and your interface).

Then comes the second to last step, which is to tie your NSOutlineView? via Cocoa Bindings to that NSTreeController?, which is through the simple addition of the value binding. Double click in the NSOutlineView?, and select the column header for the left-most column, and go to the Bindings in the Inspector:

Really, that's about it for now, compile, and run your application, and you shoudl be all set!

Exercises for the reader:

  1. Three levels? Five? Eight? Thirteen?!?
  2. Add more custom controls that bind to your controllers inside Interface Builder

Download source

Page last modified on June 16, 2006, at 09:16 PM
Search bleep. open source wiki