How to Use Cocoa Bindings and Core Data in a Mac App
This is a blog post by Andy Pereira, a software developer at USAA in San Antonio, TX, and freelance iOS and OS X developer. Lately we’re starting to write more Mac app development tutorials on raywenderlich.com, since it’s a natural “next step” for iOS developers to learn! In our previous tutorial series by Ernesto Garcia, […] By Andy Pereira.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Use Cocoa Bindings and Core Data in a Mac App
45 mins
NSArrayController
Now that you have your Entity working, it’s time to set up an NSArrayController. You’re likely wondering “what is an NSArrayController, and why do I need it?” :]
An NSArrayController is a bindings compatible class, adding features for sorting and selection management. When you populate a table with data from an array, you typically have to calculate which row a user has selected from the table, and grab the object from that index in the array. NSArrayController provides you with a method to return the object that is associated with whichever table row has been selected. This prevents you from having to do copious amounts of login in methods like selectionDidChange:, and sometimes even removes the need to have them at all. In this tutorial, you’ll actually get rid of selectionDidChange: entirely, giving you a chance to see how much work Bindings really will do for you.
An NSArrayController, as its name implies, controls an array, or collection, of objects. It can also be used to manage the relationships of an NSManagedObject, which is usually used to create Core Data models. There are also Object, Dictionary, Tree, and User Default Controllers that can be used with Bindings.
For instance, the Bug class that you created earlier is a sub-class of NSManagedObject and you’ll be using NSArrayController to work with the Bug class.
Open MasterViewController.h, and add the following property:
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
Now switch to AppDelegate.m, and add the following to the end of applicationDidFinishLaunching::
self.masterViewController.managedObjectContext = self.managedObjectContext;
This will allow you to use the same instance of the managedObjectContext that is created when the app is loaded, from the MasterViewController. This is going to be critical for setting up the NSArrayController.
Switch to MasterViewController.xib, and drag an Array Controller from the Object Library (third tab on the lower half of the right sidebar) to the objects list in the Document Outline:
Select the Array Controller, hit “Enter,” and rename the Array Controller to BugArrayController.
Note: it may appear that the name change did not take place when you enter the new name for the Array Controller. Just switch to some other file and then switch back to MasterViewController.xib. Now you should see that the array controller shows up with the correct name! :]
Note: it may appear that the name change did not take place when you enter the new name for the Array Controller. Just switch to some other file and then switch back to MasterViewController.xib. Now you should see that the array controller shows up with the correct name! :]
Select BugArrayController in the Document Outline, then select the Attributes Inspector in the right sidebar. Under Object Controller, change Mode to “Entity Name”; for Entity Name, enter “Bug”; and finally check the box “Prepares Content”, as shown in the following screenshot:
Entering the name Bug for entity name tells the BugArrayController that it is going to be managing Bug objects, while “Prepares Content” will make the BugArrayController grab any content from the managed object context.
Switch to the Bindings Inspector — the 7th tab on the right sidebar. Under “Parameters,” expand “Managed Object Context.” Check “Bind To,” and in the drop down, select “File’s Owner.” Change the Model Key Path from “self” to “managedObjectContext”, as shown below:
You have just set the BugArrayController to use the objects found in MasterViewController’s managedObjectContext. Again, this is another great example on how using an NSArrayController eliminates the need to write a bunch of boiler plate or glue code.
Go ahead — Build and Run your app! Your app should look the same as before, but make sure the Log is not giving you any warnings or errors.
You may not realize it yet, but you have just created something wonderful: your BugArrayController will now contain any and all Bug entities that are created in your managedObjectContext!
Bindings
While working in XCode is hardly comparable to dabbling in the dark arts, Cocoa Bindings isn’t too far off from appearing magical! :] Now you’re finally going to try out Bindings.
Switch to MasterViewController.xib, Control-drag from the plus (+) button to the BugArrayController and select the “add:” action from the popup menu, as below:
Do the same for the “-” button, but this time select “remove:”.
Now, whenever you click “+”, the NSArrayController will add a Bug entity to the managedObjectContext, and it will also remove one whenever you click “-“.
Wow, pretty easy, eh? Just think of all the glue code you didn’t have to write! :]
Next select the textfield under “Name” in the interface. With the Bindings Inspector selected, expand Value under the Value section. Check the Bind To checkbox, make sure the dropdown has BugArrayController selected, and enter name for the Model Key Path as demonstrated in this screenshot:
Remember how NSArrayControllers manage what objects are selected in a table? Whatever row is selected in the table a Bug object resides in an array within the NSArrayController called
selectedObjects
at index 0. When using the bindings view in Interface Builder, the “selection” key refers to this same object. Using “name” for model key path refers to the “name” property of the Bug object. The name field will now display the name value in whatever Bug has been selected in the table.
Next, time to set up the table view!
Note: In this tutorial, the NSTableView on the view has been changed to be cell-based. As this tutorial is only an introduction to Cocoa Bindings, it’s likely easier to grasp the tutorial concepts this way, as opposed to using a View-based NSTableView. Apple cautions that you should be extremely familiar with bindings and View-based table views before using them together.
Note: In this tutorial, the NSTableView on the view has been changed to be cell-based. As this tutorial is only an introduction to Cocoa Bindings, it’s likely easier to grasp the tutorial concepts this way, as opposed to using a View-based NSTableView. Apple cautions that you should be extremely familiar with bindings and View-based table views before using them together.
Select the TextCell Column in the TableView. This step can be a bit tricky, as the first click on the table will select the ScrollView, the second click will select the tableView, the third click will select the column, and the fourth click will select the individual TextCell column.
However, you can instead choose to use the Document Outline to expand the table view structure and find the column that way. Switch to the Attributes inspector, and once the column is properly selected, the inspector will display information about the column like this:
Switch back to the Bindings Inspector, and expand Value. Check the Bind To box, make sure BugArrayController is selected in the drop down, and enter name for the Model Key Path, exactly as you did with the name textfield.
As with setting up the binding on the “name” text field, you are setting the table to display the value for “name” for all of the objects in the NSArrayController. However, using the “arrangedObjects” key returns all of the objects, which is exactly what the table needs, as you are wanting all of the Bug objects to be listed out.
Save your changes — time to Build and Run the application!
Click the + button — it should add an entry to the table view, and the Name textfield should be empty. Enter the name “Lady Bug” in the name field, and click Enter. You should now see the name Lady Bug in the table and in your name field:
Quit your app by selecting ScaryBugsApp/Quit(⌘+Q). Run the app in Xcode again, and you should still see Lady Bug in the table. If you did, you have successfully set up bindings! Congratulations! :]
Note: If you stop the app in Xcode, or close the app via the close button, instead of quitting the app as mentioned above, your changes will not be saved. So make sure to follow the steps as directed! :]
Note: If you stop the app in Xcode, or close the app via the close button, instead of quitting the app as mentioned above, your changes will not be saved. So make sure to follow the steps as directed! :]