Learn Objective-C on the Mac - Mark Dalrymple [53]
Next, Section 4 checks to see if selectedRow is 0 or higher. This check is important, because there’s a real chance that Section 3 set it to -1! Consider the case where we only have one object in the array, and click the “remove” button: At the outset, selectedRow would be 0 (the index of the only row in the array), but after Section 3 it would be -1, which Section 4 handles by just skipping the rest of the method.
Finally, Section 5 deselects everything in the table view, then selects what we now want for the selected row, and finally updates all the views based on the current selection. It may not seem obvious, but it’s important to first deselect all rows in the table view, otherwise the tableViewSelectionDidChange: delegate method may not always be called (because often, after deleting a row, the selected row index itself will be the same number, and the table view has no way of knowing that we’ve deleted an object from our content array, making the row index number now refer to a different object).
Now you should be able to compile and run your app, and see that you can now also delete the selected villain, and the values in the controls will change to match the new selection.
In Conclusion
You’ve now seen a simple demonstration of how to maintain a list of items, display them in a table view, and edit the details for the selected item in a separate set of controls. You’ve learned a bit about how NSTableView uses its dataSource to access items for display and editing, and seen how it informs its delegate when the selection changes, allowing you to manually update the content in views that are dependent on the table view’s selection.
If you’re familiar with other desktop GUI development environments, some of this may have seemed a bit foreign to you, but hopefully you can see some of the advantages included in the approach that Cocoa supports, such as providing a clean division between code and GUI layout. However, at this point it’s time for a confession: the way we’ve been doing things in Chapters 4 and 5 isn’t necessarily the best way to do these sorts of things in Cocoa. As simple as it’s all been so far, we’ve actually been showing you the hard way to solve these problems! During the past few years, a new approach to GUI programming has taken root in the Cocoa community, and is becoming more prevalent all the time; it’s a technology called Cocoa Bindings, and it’s the topic of Chapter 6.
Chapter 6
Cocoa Bindings
In Chapters 4 and 5, you learned about how to connect a controller object to various kinds of view objects, both to display values and to retrieve new values in response to user actions. In our examples, we typically had one small action method for each view (triggered when the user edited the value displayed in the view), plus one large updateDetailViews method that updated the contents of all the views at once (called whenever the selection changed). That’s fine for a simple project, but there are some problems with that approach. First of all, there’s a scalability issue. Imagine having not ten, but a hundred views. Following our approach, you’d end up with a controller having a hundred small action methods, and one huge method to push values into all of the views!
Plus, we really have some tight coupling between our controller and its associated views. For example, what if you start off with an NSDatePicker for displaying and editing a date, but later decide you want to use an NSTextField? Besides modifying the GUI, you’d also have to change the outlet, the corresponding action method, and the updateDetailViews method.
Fortunately for us, Apple recognized this problem some time ago, and since Mac OS X 10.3 it has included a technology called Cocoa Bindings that solves many of these problems. Cocoa Bindings lets you use Interface Builder to configure a view so that it retrieves its value and passes changes back to a model object more or less automatically. All you do is tell it which