Picker View Processing

Ratings:
(4)
Views:138
Banner-Img
  • Share this blog:

UIPickerView

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.  

UIPickerViewDelegate

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.

  • (CGFloat)pickerView:(UIPickerView *) pickerView rowHeightForComponent:

(NSInteger) component

  • (CGFloat)pickerView:(UIPickerView *) pickerView widthForComponent:

(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

Using a Picker

  1. Create a new View-based Application named A Picker.
  2. Open xib in Interface Builder.
  3. Drag a picker view from the library to the canvas. Right-click and notice that the control doesn’t have the choices a UIDatePicker has (Figure 13-10).

     Slide130                                 Figure 13-10 A UIPickerView has less outlets and actions than a UIDatePicker  

  1. Add a button to the canvas.
  2. Save and exit Interface Builder.
  3. Create a new NSObject named MyPickerDelegate and change it to adopt the UIPickerViewDelegate and UIPickerViewDataSource Have MyPickerDelegate implement the needed methods (Listings 13-7 and 13-8).
  4. Open APickerViewController and add IBOutlets for UIPickerView and MyPickerDelegate (Listing 13-9). Add an IBAction called
  5. Implement the changeColor action (Listing 13-10).
  6. Save and Open APickerViewController.xib in Interface Builder.
  7. Connect File’s Owner changeColor action to the button’s Touch Up Inside
  8. Connect File’s Owner myPicker outlet to the
  9. Drag an object from the library to the document Change the object’s type to MyPickerDelegate.
  10. Connect the File’s Owner myPickerDelegate outlet to the object just added.
  11. Connect the UIPickerView’s dataSource and delegate outlets to the newly added

     Slide131   Figure 13-11 Running the application in iPhone Simulator

  1. Save and exit Interface Builder.
  2. Click Build And Go to run the application in iPhone Upon pushing the button, the debugger console logs the picker’s chosen color (Figure 13-11 and Listing 13-11).

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; }

  • (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

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.

  1. Open APicker application in Xcode.
  2. Modify MyPickerDelegate’s numberOfComponentsInPickerView to return the number 2 (Listing 13-13).
  3. Click Build And Notice the picker now shows two independent spinning wheels (Figure 13-12).
  4. Add a second value Call the array myData2 and initialize it in the init method, as you did before with myData (Listings 13-12 and 13-13).
  5. Create two constants representing the different wheels: COLOR_WHEEL for the wheel containing the myData values and SHADE_WHEEL for the wheel containing the myData2 Remember, you define constants in a class’s header file (Listing 13-12).
  6. Modify the numberOfRowsInComponent method and titleForRow method to reflect the newly added
  7. Open m and modify the changeColor method to reflect the second wheel (Listing 13-14).

 

Figure 13-12 A UIPickerView with two components

  Slide131Slide132   Figure 13-13 Running the application in iPhone Simulator  

  1. Click Build And The application shows two wheels. Upon clicking the button, the debugger console logs the first wheel’s color and the second wheel’s shade (Figure 13-13 and Listing 13-15). Listing 13-12 MyPickerDelegate.h modified to reflect two wheels

#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];  

Loading UIImageViews into a UIPickerView

  1. Open the APicker application created earlier—not the project with two components, but the earlier project with only one component.
  1. Replace the pickerView:titleForRow:forComponent: method in MyPickerDelegate with pickerView:viewForRow:forComponent: (Listing 13-16).
  2. Add the images png, wizard.png, and tux.png to the project. You can find these images in the book’s resources folder.

            Modify the MyPickerDelegate’s init: method so it loads UIImageViews rather than strings into myData (Listing 13-16).

  1. Modify the pickerView:didSelectRow:inComponent: so it only logs the row and component to the debugger console (Listing 13-16).
  2. Save and build.
  3. Open xib and remove the button.
  4. Save and exit Interfacebuilder.
  5. Click Build And The application loads the images into the UIPickerView (Figure 13- 14).

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

  Slide132       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

Recommended Courses

1/15

About Author
Authorlogo
Name
TekSlate
Author Bio

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