A UIPickerView allows the selection of one or more value sets. A UIPickerView consists of rows and components. Think of the component as the column and the row as the row. So ifyou had a three-wheel UIPickerView, the third wheel is the third component. A UIPickerView must have an associated class that adopts the UIPickerViewDelegate and a class that adopts the UIPickerViewDataSource. The same class can adopt both protocols.
The UIPickerViewDelegate protocol dictates how a UIPickerView is to construct itself. This protocol contains five methods a class might implement when adopting this protocol: the pickerView:rowHeightForComponent:, pickerView:widthForComponent:, pickerView :titleForRow:forComponent:, pickerView:viewForRow:forComponent:reusingView, and pickerView:didSelectRow:inComponent: methods. Width and Height The pickerView:rowHeightForComponent: and pickerView:widthFor Component: methods set a picker’s component dimensions. Remember, a picker’s component can contain rows of strings or view controls, like a UIImageView. These methods accommodate controls by allowing you to set a component’s height and width. Each method’s signature follows.
(NSInteger) component
(NSInteger) component Content The pickerView:titleForRow:forComponent: and pickerView:viewForRow:for Component: methods provide a component’s title or view. The title or the view is what is displayed as the rows in a picker. You must implement one of the two methods. If using a string, implement the pickerView:titleForRow:forComponent: method; if using a view, implement the pickerView:viewForRow:forComponent: method. Each method’s signature follows.(NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger) row forComponent: (NSInteger) component(UIView *)pickerView:(UIPickerView *)pickerView viewForRow: (NSInteger) row forComponent:(NSInteger)component reusingView: (UIView *)view Selecting The UIPickerView calls the pickerView:didSelectRow:inComponent: method when a user selects a component’s row. It takes the component’s index number and the row’s index number as parameters, so you can determine the component selected and the component’s row. The method’s signature follows.(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component UIPickerViewDatasource A UIPickerViewDatasource handles a UIPickerView’s data. It contains two methods you should define when adopting this protocol: the numberOfComponentsInPickerView: and pickerView:numberOfRowsInComponent: methods. The numberOfComponentsInPickerView: method returns how many components, or columns, a picker must display.(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger) component The pickerView:numberOfRowsInComponent: method returns a component’s row count.(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger) component
Figure 13-10 A UIPickerView has less outlets and actions than a UIDatePicker
Figure 13-11 Running the application in iPhone Simulator
Listing 13-7 MyPickerDelegate.h #import <Foundation/Foundation.h> @interface MyPickerDelegate : NSObject <UIPickerViewDelegate, UIPickerViewDataSource> { NSArray * myData; } @property (nonatomic, retain) NSArray * myData; @end Listing 13-8 MyPickerDelegate.m #import "MyPickerDelegate.h" @implementation MyPickerDelegate @synthesize myData; - (id) init { if([super init] == nil) return nil; myData = [[NSArray alloc] initWithObjects:@"Red",@"Yellow",@"Green",@"Blue", @"Purple", @"Orange", @"Black", @"Gray", @"Tan", @"Pink", @"Coral", nil]; return self; }
NSLog(@"picked row: %i, component: %i", row, component); NSLog(@"the value: %@", [self.myData objectAtIndex:row]); } (NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView { return 1; }(NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component { return [self.myData count]; }(NSString *) pickerView: (UIPickerView *) pickerView titleForRow: (NSInteger) row forComponent: (NSInteger) component { return [self.myData objectAtIndex:row]; }(void)dealloc { [myData release]; [super dealloc]; } @end Listing 13-9 APickerViewController.h #import <UIKit/UIKit.h> #import "MyPickerDelegate.h" @interface APickerViewController : UIViewController { IBOutlet UIPickerView * myPicker; IBOutlet MyPickerDelegate * myPickerDelegate; } @property (nonatomic, retain) IBOutlet UIPickerView * myPicker; @property (nonatomic, retain) IBOutlet MyPickerDelegate * myPickerDelegate; - (IBAction) changeColor: (id) sender; @end Listing 13-10 APickerViewController.m #import "APickerViewController.h" @implementation APickerViewController @synthesize myPicker; @synthesize myPickerDelegate; NSLog(@"the color is: %@", (NSString *)[myPickerDelegate.myData objectAtIndex: [myPicker selectedRowInComponent:0]]); }(void)dealloc { [myPickerDelegate release]; [myPicker release]; [super dealloc]; } @end Listing 13-11 Debug console output from running APicker application [Session started at 2009-02-06 22:57:09 -0500.] 2009-02-06 22:57:13.007 APicker[429:20b] picked row: 1, component: 0 2009-02-06 22:57:13.008 APicker[429:20b] the value: Yellow 2009-02-06 22:57:14.687 APicker[429:20b] picked row: 3, component: 0 2009-02-06 22:57:14.687 APicker[429:20b] the value: Blue 2009-02-06 22:57:16.540 APicker[429:20b] picked row: 8, component: 0 2009-02-06 22:57:16.541 APicker[429:20b] the value: Tan 2009-02-06 22:57:17.499 APicker[429:20b] the color is: Tan 2009-02-06 22:57:21.215 APicker[429:20b] picked row: 10, component: 0 2009-02-06 22:57:21.215 APicker[429:20b] the value: Coral 2009-02-06 22:57:22.547 APicker[429:20b] the color is: Coral A UIPickerView must have helper classes adopting the UIPickerViewDelegate and UIPickerViewDataSource protocols. In this example, you had one class, MyPickerDelegate, adopt both protocols. The delegate uses a simple NSArray to hold NSString objects. Because the data is simple strings, the delegate implements the titleForRow method. When a user selects a row, the didSelectRow method logs the row, component, and value to the debugger console.
Figure 13-12 A UIPickerView with two components
Figure 13-13 Running the application in iPhone Simulator
#import <Foundation/Foundation.h> #define COLOR_WHEEL 0 #define SHADE_WHEEL 1 @interface MyPickerDelegate : NSObject <UIPickerViewDelegate, UIPickerViewDataSource> { NSArray * myData; NSArray * myData2; } @property (nonatomic, retain) NSArray * myData; @property (nonatomic, retain) NSArray * myData2; @end Listing 13-13 MyPickerDelegate.m modified to reflect two wheels #import "MyPickerDelegate.h" @implementation MyPickerDelegate @synthesize myData; @synthesize myData2; - (id) init { if([super init] == nil) return nil; myData = [[NSArray alloc]initWithObjects: @"Red", @"Yellow", @"Green", @"Blue", @"Purple", @"Orange", @"Black", @"Gray", @"Tan", @"Pink", @"Coral", nil]; myData2 = [[NSArray alloc] initWithObjects: @"Very Dark", @"Dark", @"Normal", @"Light", @"Very Light", nil]; return self; }(NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView { return 2; }(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { NSLog(@"picked row: %i, component: %i", row, component); if(component == COLOR_WHEEL) NSLog(@"the value: %@", [self.myData objectAtIndex:row]); else NSLog(@"the value: %@", [self.myData2 objectAtIndex:row]); } - (NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component { if(component == COLOR_WHEEL) return [self.myData count]; else return [self.myData2 count]; } - (NSString *) pickerView: (UIPickerView *) pickerView titleForRow: (NSInteger) row forComponent: (NSInteger) component { if(component == COLOR_WHEEL) return [self.myData objectAtIndex:row]; else return [self.myData2 objectAtIndex:row]; } - (void)dealloc { [myData release]; [myData2 release]; [super dealloc]; } @end Listing 13-14 The changeColor method modified to reflect two wheels - (IBAction) changeColor: (id) sender { NSLog(@"the color is: %@ and the shade is: %@", (NSString *) [myPickerDelegate.myData objectAtIndex: [myPicker selectedRowInComponent: COLOR_WHEEL]], (NSString *)[myPickerDelegate .myData2 objectAtIndex: [myPicker selectedRowInComponent:SHADE_ WHEEL]]); } Listing 13-15 Debugger console logging from running APicker application [Session started at 2009-02-06 23:01:29 -0500.] 2009-02-06 23:01:32.630 APicker[550:20b] picked row: 7, component: 0 2009-02-06 23:01:38.632 APicker[550:20b] the value: Orange --- snip --- 2009-02-06 23:01:39.508 APicker[550:20b] the color is: Orange and the shade is: Very Light Using more components involves adding code to check which component was selected. But note, rather than using the raw integers, in this task, you created constants for both components. Each delegate’s method then checks which component the user selected. if(component == COLOR_WHEEL) return [self.myData objectAtIndex:row]; else return [self.myData2 objectAtIndex:row];
Modify the MyPickerDelegate’s init: method so it loads UIImageViews rather than strings into myData (Listing 13-16).
NOTE Notice that the pickerView:viewForRow:forComponent method takes a UIView. So, similar to custom table cells, you can also create custom picker rows using a UIView.
Figure 13-14 A UIPickerView that uses UIImageView objects as its components
Listing 13-16 MyPickerDelegate.m modified to load images into the UIPickerView #import "MyPickerDelegate.h" @implementation MyPickerDelegate @synthesize myData; - (id) init { if([super init] == nil) return nil; UIImageView * one = [[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"wizard.png"]]]; UIImageView * two =[[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @"tux.png"]]]; UIImageView * three =[[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"money.png"]]]; myData = [[NSArray alloc] initWithObjects:one,two,three,nil]; return self; }(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent: (NSInteger)component { NSLog(@"picked row: %i, component: %i", row, component); }(NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView { return 1; }(NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component { return [self.myData count]; }(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger) row forComponent:(NSInteger)component reusingView:(UIView *)view { return [self.myData objectAtIndex:row]; } @end
You liked the article?
Like : 0
Vote for difficulty
Current difficulty (Avg): Medium
1/15
TekSlate is the best online training provider in delivering world-class IT skills to individuals and corporates from all parts of the globe. We are proven experts in accumulating every need of an IT skills upgrade aspirant and have delivered excellent services. We aim to bring you all the essentials to learn and master new technologies in the market with our articles, blogs, and videos. Build your career success with us, enhancing most in-demand skills in the market.
Stay Updated
Get stories of change makers and innovators from the startup ecosystem in your inbox