Cocoa Programming for Mac OS X - Aaron Hillegass [63]
Figure 11.13. Image View Binding
Select the box. In the Bindings Inspector, under the Title With Pattern heading, bind Display Pattern Title1 to Cars (our custom name for the array controller). Set the Controller Key to selection and the Model Key Path to makeModel. Set the Display Pattern to Details for %{title1}@. Set the No Selection Placeholder to Figure 11.14. Box Binding Let’s also make the text of the first two columns appear in bold if the car is on special. Bind the Font Bold of the Static Text (NSTextField) in each of the first two columns to Table Cell View. Set the Model Key Path to objectValue. onSpecial (Figure 11.15). Figure 11.15. Specials Appear in Bold You are done. Build and run the application. Saving and loading should work. Undo should work. Magic, eh? How Core Data Works Figure 11.16. Overview of Core Data So, the NSPersistentDocument reads in the model you created and uses it to create an instance of NSManagedObjectModel. In our case, the managed object model has one NSEntityDescription (which describes our Car entity). That entity description has several instances of NSAttributeDescription. Once it has the model, the persistent document creates an instance of NSPersistentStoreCoordinator and an instance of NSManagedObjectContext. The NSManagedObjectContext fetches instances of NSManagedObject from the object store. While those managed objects are in memory, the managed object context observes them. Whenever the data inside the managed objects is changed, the managed object context registers the undo action with the document’s NSUndoManager. The managed object context also knows which objects have been changed and need to be saved. So, among the classes in the Core Data framework, you will find yourself interacting with NSManagedObjectContext the most. To fetch objects, you will use NSManagedObjectContext. To save changes to your object graph, you will use NSManagedObjectContext. Given that we are probably going to add cars to the system when we purchase them, it would be nice if the datePurchased attribute were set to the current date. One good way to do this is to subclass NSArrayController and override its newObject method. Create a new file of type Objective-C class. It will be a subclass of NSArrayController. Name it CarArrayController. In CarArrayController.m, remove the init and dealloc the template created and override newObject: - (id)newObject { id newObj = [super newObject]; NSDate *now = [NSDate date]; [newObj setValue:now forKey:@"datePurchased"]; return newObj; } Open MyDocument.xib in the Interface Builder editor and select the array controller. In the Identity Inspector, set the class to be CarArrayController. (Be sure that you are in the Identity Inspector, not the Attributes Inspector; this array controller is still holding on to an array of instances of the Car entity.) See Figure 11.17. Figure 11.17. Change Class of Array Controller Build and run your application. When new cars are added, their datePurchased attribute should be initialized to the current date. For the More Curious: View-Based versus Cell-Based Table Views Cell-based table views have been around since Cocoa’s origins at NeXT. This type of table view uses cells for performance reasons and works very well for displaying simple data. But customization can be challenging, and incorporating animation or interactive controls, such as buttons, into cells can be extremely challenging. Cell-based table views are your only choice if you are targeting Mac OS X 10.6 or earlier. View-based
Although you have written no code, many objects will be created to make this work. Figure 11.16 is a diagram of some of them.
You have now used both view-based and cell-based table views: view based in this chapter, cell based in the SpeakLine exercise. You are probably wondering why there are two types and which one you should choose.