In the lead-up to this project, we made it pretty clear that implementing your own picker view (UIPickerView)
is going to be a bit different from other UI features you’ve added
previously—including the date picker you just finished. This doesn’t
mean it will be difficult,
just different. Because a picker view starts out empty and can contain
anything we want, we need to provide it with data to display and
describe how it should be displayed.
Implementation Overview
This project, named MatchPicker, will implement an instance of UIPickerView
that presents two scrolling wheels of information: animal names and
animal sounds. We’ll use some simple logic to identify whether an animal
matches the correct sound and display a positive or negative response
to the user. In short, a very easy matching game. After we have the
basics in place, we’ll spruce things up by changing the animal names to
actual pictures of the names. The final result that we’re aiming for is
shown in Figure 1.
Setting Up the Project
Because this is a picker view that must conform to the UIPickerViewDataSource and UIPickerViewDelegate
protocols, the setup we need to complete is just a teensy bit different
from earlier projects. Get started by opening Xcode and creating a
View-Based Application named MatchPicker.
Conforming to a Protocol
To tell Xcode that one of our
classes is going to conform to a protocol (or, in this case, multiple
protocols), we need to edit the header file for the class and include
the protocols in the @interface line.
For this project, we want our view controller (MatchPickerViewController) to conform to the UIPickerViewDataSource and UIPickerViewDelegate protocols. Open MatchPickerViewController.h and edit the @interface line to read as follows:
@interface MatchPickerViewController : UIViewController <UIPickerViewDataSource,
UIPickerViewDelegate> {
Adding a comma-separated list of the names of the protocols we’ll be implementing within the angle brackets <> is all we need to do to tell Xcode that we’re going to conform to a protocol. The rest of the project setup is pretty standard.
Adding Outlets but Not Actions
Amazingly, this project requires only two outlets and no actions. The outlets will correspond to two labels (UILabel): lastAction will display the last action the user performed in the picker, and matchResult will be used to display feedback on whether the user successfully matched animal to sound.
So, why no action? Because the protocols we’re conforming to define a method, pickerView:didSelectRow:inComponent, that will automatically be called when the user makes a selection. By adding the protocols to the @interface line, we’ve effectively added everything we’ll need to connect to inside of Interface Builder.
Edit the MatchPickerViewController.h file to include outlets and property declarations for the lastAction and matchResult labels, as shown in Listing 1.
Listing 1.
#import <UIKit/UIKit.h>
@interface MatchPickerViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> { IBOutlet UILabel *lastAction; IBOutlet UILabel *matchResult; }
@property (nonatomic, retain) UILabel *lastAction; @property (nonatomic, retain) UILabel *matchResult;
@end
|
Next, add the corresponding @synthesize
lines to the implementation file (MatchPickerViewController.m) for each
of the defined properties. These should be located after the @implementation directive:
@synthesize lastAction;
@synthesize matchResult;
Releasing the Objects
Edit the dealloc
method in MatchPickerViewController.m to release the two labels we’ve
retained. We’ll need to revisit this with a few more edits later on,
but, for now, the method should read as follows:
- (void)dealloc {
[lastAction release];
[matchResult release];
[super dealloc];
}
Make
sure you’ve saved the view controller header and implementation files,
and then let’s turn our attention to hammering out the picker view
interface with Interface Builder.
Adding a Picker View
Because the picker view
is controlled mostly by the protocols we’ll be implementing, there’s
surprisingly little to do in Interface Builder. Open the
MatchPickerViewController.xib file, and make sure the view it contains
is also open.
Using the Objects Library (Tools, Library), click and drag an instance of UIPickerView
to the view, positioning it at the top of the iPhone interface. That’s
really all there is to it. If you open up the Attributes Inspector
(Command+1), you’ll notice that there is only a single attribute for the
picker view—whether or not the selection indicator is present. You can
turn this on or off, depending on how you feel it works with the
aesthetics of your application. Figure 2 shows the picker added to the view, along with its available attributes.
By the Way
When you add a UIPickerView
to your view, it will display with a list of cities as the default
contents. This won’t change! Because the actual contents of the picker
are determined by the code you write, you’re not going to see the final
result until you run the application.
Connecting to the Data Source and Delegate Protocol Outlets
Remember that we didn’t add any actions or outlets for the picker view to connect to, but we did declare that the MatchPickerViewController class we’re writing will conform to the UIPickerViewDataSource and UIPickerViewDelegate protocols. Behind the scenes, this created the necessary outlets that the picker will need to connect to.
Control-drag from
either the visual representation of the picker within your view or its
icon in the Document window to the File’s Owner icon. When you release
your mouse button, you’ll be prompted to connect to either the Delegate
or Data Source outlets, as shown in Figure 3. Choose the Delegate option to create the first connection.
After the delegate
connection is made, repeat the exact same process, but this time choose
Data Source. When both connections are in place, the picker is as
“configured” as we can get it in Interface Builder. All the remaining
work must take place in code.