Learn Objective-C on the Mac - Mark Dalrymple [74]
You can select these pair-wise either by “drawing a box” around them, or by first clicking on the text field, and then Shift-clicking on its corresponding label. While dragging things around, you’re bound to inadvertently drag something where you didn’t want to put it. Remember that Edit➤Undo (⌘Z) is your friend!
Now let’s set up the image view for the depiction attribute, and the text view for the details attribute. Find an NSImageView in the Library and drop it just below the text fields, then find an NSTextView and put it next to the image view. Drag the old Depiction and Details labels up above their views, and resize the views so that your window looks something like Figure 7-9.
Figure 7-9. Our window is starting to shape up!
Now we just have to configure the new controls so that they’ll actually display something. Select the image view, and in the Bindings Inspector open up the Value binding configuration. Choose Mythical Person Array Controller in the popup list, selection in the Controller Key combo box, depiction in the Model Key Path combo box, and NSKeyedUnarchiveFromData in the Value Transformer combo box. Now switch to the Attributes Inspector (⌘1), and click to turn on the Editable checkbox (so that a user can drag an image into the image view).
Next, select the text view. NSTextView is able, by default, to display rich text, which is a great feature but comes at a price: In Cocoa, rich text is represented by instances of NSAttributedString, a class that’s a lot more complicated than NSString, and not something we want to get into here and now. In order for the text view to be able to bind its display value to a plain old string, we have to turn off rich text handling. So, in the Attributes Inspector, click to turn off the Rich Text checkbox (if you don’t see that, you’ve probably selected the text view’s superview, an NSScrollView. Click the text view once more to select the NSTextView inside). Now, switch to the Bindings Inspector again, and open the configuration for the Value binding. Choose Mythical Person Array Controller, selection, and details in the relevant popup and combo boxes.
Now save your work in Interface Builder, switch back to Xcode, and hit the Run button. If all goes well, your interface comes up, fully functional! You can create a new Mythical Person (or select one you created earlier), drag an image (from the Finder, or a web page, and the like) into the image view, and the image will appear in the table view immediately. When you choose File➤Save from the menu, or quit the application, the image you dragged in will be saved to the data store along with the rest.
The last thing that isn’t quite satisfying about our GUI is the set of controls for entering numeric values. Sure, you can type a number into a text field, but it’s somewhat error-prone (since a user can type in any text they want) and is generally not the way people expect to enter numbers much of the time these days. Let’s replace each text field with a slider and label combo, like we did in the Preferences window for DungeonThing in Chapter 6.
Back in Interface Builder, select and delete the text field controls for power, divinity, and goodness. Leave the labels where they are though, because they’ll point right at the new controls. Now, find a horizontal slider in the Library, and drag it to the window. Open the Attributes Inspector, and set the slider’s min and max values to 0 and 100. Also, click to turn on the Continuous checkbox. Now find a label in the Library, and drag it out to the right of the slider, all the way to the right edge of the view. We’re going to configure this label with a binding so that it will display the value set by the slider, so set its text to “100” in the nib file; that way you can see the largest amount of space it will take up. Then resize the slider to fill up most of the gap.
Before going on, there’s an issue that we need to address. When NSSlider passes along its value (to the underlying MythicalPerson), it sends a floating-point value instead