iOS Programming Recipe 9: Adding Multiple Columns to UIPickerView

In my last article I left off on the UIPickerView with some basic functionality. This week I want to expand on that functonality and show a few other bits of functionality that can be used. What we did in Recipe 7 was show a picker with a single column. In this article I want to expand on that and show how to use two columns: The second column will change the alpha value for our color.

Assumptions

Reworking the Data Source

Alright, let’s get into this! The first thing we’ll want to do is edit these two methods:


// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    //One column
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    //set number of rows
    return [self.colorArray count];
}

The first data source method should be obvious! We’ll simply change the return value from 1 to 2 this sets it to two columns (components). The second data source method requires a bit more work, Although it’s not too much. The second method just sets up a return value based on which column was selected.


// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    //Two columns
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
   //set number of rows
   if(component== 0)
   {
       return [self.colorArray count];
   }
   else
   {
       return [self.alphaArray count];
   }
}

If you were paying attention, you’ll see we added a new array, so we’ll need to add that to the .h file and allocate and initialize it in the .m file. Do that as follows.

pickit.h:


@interface ViewController : UIViewController    <UIPickerViewDataSource,UIPickerViewDelegate>

@property (strong, nonatomic) IBOutlet UILabel      *color;
@property (strong, nonatomic) IBOutlet UIPickerView *picker;
@property (strong, nonatomic)          NSArray      *colorArray;
@property (strong, nonatomic)          NSArray      *alphaArray;

@end

pickit.m:


- (void)viewDidLoad
{
    [super viewDidLoad];

    self.colorArray = @[@"Blue",@"Green",@"Orange",@"Purple",@"Red",@"Yellow"];
    self.alphaArray = @[@"50",@"100",@"150",@"200",@"250"];
}

Alright, now we’re ready for the third method in the data souce. like the second method we’ll use a conditional to let the method know how to populate each column. We’ll set the values in colorArray to the 1st column and the values in the alphaArray to the 2nd column. This is exactly the same thing we did in Recipe 7 but with an added array and conditional.

Before:


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return [self.colorArray objectAtIndex:row];
}

After:


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if(component == 0)
    {
        return [self.colorArray objectAtIndex:row];
    }
    else
    {
        return [self.alphaArray objectAtIndex:row];
    }
}

Sweet, Now we’re ready to rework the delegate.

Reworking the Delegate

This last piece is actually quite simple. All we’re doing now is setting the alpha value in all of the colors in the case statement:

Where we left off last time:


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    NSLog(@"Selected Row %d", row);
    switch(row)
    {
        case 0:
            self.color.text = @"Blue #0000FF";
            self.color.textColor = [UIColor colorWithRed:0.0f/255.0f green: 0.0f/255.0f blue:255.0f/255.0f alpha:255.0f/255.0f];
            break;
        case 1:
            self.color.text = @"Green #00FF00";
            self.color.textColor = [UIColor colorWithRed:0.0f/255.0f green: 255.0f/255.0f blue:0.0f/255.0f alpha:255.0f/255.0f];
            break;
        case 2:
            self.color.text = @"Orange #FF681F";
            self.color.textColor = [UIColor colorWithRed:205.0f/255.0f green:   140.0f/255.0f blue:31.0f/255.0f alpha:255.0f/255.0f];
            break;
        case 3:
            self.color.text = @"Purple #FF00FF";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:   0.0f/255.0f blue:255.0f/255.0f alpha:255.0f/255.0f];
            break;
        case 4:
            self.color.text = @"Red #FF0000";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:   0.0f/255.0f blue:0.0f/255.0f alpha:255.0f/255.0f];
            break;
        case 5:
            self.color.text = @"Yellow #FFFF00";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:   255.0f/255.0f blue:0.0f/255.0f alpha:255.0f/255.0f];
            break;
    }
}

we’ll modify this method by creating some local variables to store the selected row in each component and then create a case statement to set the another variable “alphaValue” to the correct value. So here’s how I modified this method.


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    NSLog(@"Selected Row %d", row);

    NSInteger firstComponentRow = [self.picker selectedRowInComponent:0];
    NSInteger secondComponentRow = [self.picker selectedRowInComponent:1];
    float alphaValue = 0.0;

    switch(secondComponentRow) {
        case 0:
            alphaValue = 50.0f/255.0f;
            break;
        case 1:
            alphaValue = 100.0f/255.0f;
            break;
        case 2:
            alphaValue = 150.0f/255.0f;
            break;
        case 3:
            alphaValue = 200.0f/255.0f;
            break;
        case 4:
            alphaValue = 250.0f/255.0f;
            break;
        default:
            alphaValue = 0.0f/255.0f;
            break;
    }

    switch(firstComponentRow)
    {
        case 0:
            self.color.text = @"Blue #0000FF";
            self.color.textColor = [UIColor colorWithRed:0.0f/255.0f green:0.0f/255.0f blue:255.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
        case 1:
            self.color.text = @"Green #00FF00";
            self.color.textColor = [UIColor colorWithRed:0.0f/255.0f green:255.0f/255.0f blue:0.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
        case 2:
            self.color.text = @"Orange #FF681F";
            self.color.textColor = [UIColor colorWithRed:205.0f/255.0f green:140.0f/255.0f blue:31.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
        case 3:
            self.color.text = @"Purple #FF00FF";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:0.0f/255.0f blue:255.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
        case 4:
            self.color.text = @"Red #FF0000";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:0.0f/255.0f blue:0.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
        case 5:
            self.color.text = @"Yellow #FFFF00";
            self.color.textColor = [UIColor colorWithRed:255.0f/255.0f green:255.0f/255.0f blue:0.0f/255.0f alpha:alphaValue];
            NSLog(@"AlphaValue is: %f",alphaValue);
            break;
    }
}

And that’s It! Now we can choose both the color and the alpha. You should have something like this:

Screen Shot 2013-01-18 at 11.58.10 PM

Wrap Up

Obviously there is a lot more that can be done with a picker, but between this recipe and recipe 7 you should be able to at least get started.

About Joe Hoffman

I am An Electrical Engineer that spends a lot of my off time doing web development and other programming. Currently I am trying to expand my knowledge with iOS and I find that writing tutorials helps me learn more thoroughly as well as provide some useful info to others.

Comments

  1. Ivan Nikolai says:

    thanks! your tutorial is very easy to understand. i just have one question, is it possible that the displayed contents of the second column depend on the row selected on the first column? i kinda visualize the first column as a folder selector and the second column as the contents of the selected folder.

    Thank you very much!

    • Hi Ivan!

      I’m glad you found this helpful. As far as I can tell, the second column has no dependency on the first column unless of course you want it to behave this way. In order to achieve this sort of behavior you would need to add some extra logic. I am not sure off hand how you would do this, but I would think you could call a method from the delegate that would change the data source values.

  2. Can u put the downloading link somewhere in the page

    • Joe Hoffman says:

      Hi Vivek,

      I’m not sure I saved the source for this one. I’ll check it out tonight and post it if available. Are you having a particular problem I can maybe help you with?

  3. this was an awesome tutorial and so simple to follow. thanks a lot man, truly appreciate it

  4. Haider Al-Qullaf says:

    Thanks for the tutorial .. I need the same project but
    Passing images to UiPickerView .
    I tried to do it as you done but only passing file name .
    Try to pass UiImage but not all images appear and
    Not ad i want .
    Thanks

  5. Joe Hoffman says:

    Hi Haider,

    If I’m understanding correctly , instead of setting the picker values to a text label you are setting them to a UIImageView?

    I would guess that your problem is that images are bigger, and therefore they take more time to load. Which could mean, not all of them are loading. You will want to load the images asynchronously to overcome this.

    That being said. I’m not exactly sure why you would want to add images to a picker view. What’s your application? I would bet that there is a better API for doing what you are trying to do.

  6. Thank you so much! I searched Google twice, once to find out how to create something like UIDatePicker with customizable options (yes, I’m a newbie) and found nscookbook.com. Then I wanted a second component, so I searched Google again and found – nscookbook.com! I think I’ll look through all your recipes before trotting off on my own again 🙂

  7. Thank you Joe! Very useful tutorials, especially for people like me who just started experimenting. May I ask: what should we do if we want the return value to depend on (the selected values on) both columns? For example, if the first component has main dishes and the second one desserts the final output to show the price? Any tips or ideas would be highly appreciated. Again, thank you!

    • Joe Hoffman says:

      HI Bob,

      What I would do is create a new method that gets called from within the didSelectRow: inComponent method. Within the didSelectRow: inComponent I would set the properties when a change to either column happened. I would have one property for each column (IE one property for dishes and one for desserts). when the didSelectRow: inComponent delegate method gets called I would simply set the property for either dishes or desserts depending on which column was selected and then call the new method. The new method would first make sure there are values in the dishes and desserts. If the values aren’t NIL, then lookup the price of the dish or dessert and add it to a temporary variable. The variable should be set to zero every time the function is called, at the end of the function set a property with the value.

      hope this helps

      • First of all, thank you for your quick reply! I understand the logic behind it but it would be extremely useful if I could see an example. I have spent many, many hours during the past weeks looking around but unfortunately it seems no one has uploaded anything similar. Have you spotted any on the Internet or do you have any sources to propose? Any help would be greatly appreciated. Once again, thank you!

  8. Hi,
    i have modified your code to have 3 wheels, and it worked, however when i changed the values to numbers the system crashes when you change a wheel. Any help is much appreciated.

    .M

    //
    // ViewController.m
    // Pickertest(multi)
    //
    // Created by Justin Shirley-Smith on 10/07/2014.
    // Copyright (c) 2014 JSS. All rights reserved.
    //

    #import “ViewController.h”

    @interface ViewController ()

    @end

    @implementation ViewController

    – (void)viewDidLoad
    {
    [super viewDidLoad];

    self.colorArray = @[@”1″,@”2″,@”3″,@”4″,@”5″,@”6″];
    self.alphaArray = @[@”1″,@”2″,@”3″,@”4″,@”5″];
    self.ThrdArray = @[@”1″,@”2″,@”3″,@”4″,@”5″];
    }

    – (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    // returns the number of ‘columns’ to display.
    – (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
    {
    return 3;

    }

    // returns the # of rows in each component..
    – (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component
    {
    if(component== 0)
    {
    return [self.colorArray count];
    }
    else
    {
    if (component==1)
    {
    return [self.alphaArray count];
    }
    else
    {
    return [self.ThrdArray count];
    }
    }
    }

    -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
    {

    if(component== 0)
    {
    return [self.colorArray objectAtIndex:row];
    }
    else
    {
    if (component==1)
    {
    return [self.alphaArray objectAtIndex:row];
    }
    else
    {
    return [self.ThrdArray objectAtIndex:row];
    }
    }
    }
    – (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
    {
    NSLog(@”Selected Row %ld”, (long)row);

    NSInteger firstComponentRow = [self.picker selectedRowInComponent:0];
    NSInteger secondComponentRow = [self.picker selectedRowInComponent:1];
    NSInteger thirdComponentRow = [self.picker selectedRowInComponent:2];
    float valueS = 1;
    float valueM = 1;
    float valueH = 1;
    float calculate = (valueS + (valueM * 60) + (valueH * 120));
    switch(thirdComponentRow) {
    case 0:
    valueS = 1;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 1:
    valueS = 2;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 2:
    valueS = 3;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 3:
    valueS = 4;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 4:
    valueS = 5;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    default:
    valueS = 1;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    }

    switch(secondComponentRow) {
    case 0:
    valueM = 1;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 1:
    valueM = 2;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 2:
    valueM = 3;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 3:
    valueM = 4;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 4:
    valueM = 5;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    default:
    valueM = 1;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    }

    switch(firstComponentRow)
    {
    case 0:
    valueH = 1;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 1:
    valueH = 2;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 2:
    valueH = 3;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 3:
    valueH = 4;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 4:
    valueH = 5;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    case 5:
    valueH = 6;
    self.color.text = [NSString stringWithFormat :@”%.2f”,calculate];
    break;
    }
    }

    @end

    .H

    //
    // ViewController.h
    // Pickertest(multi)
    //
    // Created by Justin Shirley-Smith on 10/07/2014.
    // Copyright (c) 2014 JSS. All rights reserved.
    //

    #import

    @interface ViewController : UIViewController

    @property (strong, nonatomic) IBOutlet UILabel *color;
    @property (strong, nonatomic) IBOutlet UIPickerView *picker;

    @property (strong, nonatomic) NSArray *colorArray;
    @property (strong, nonatomic) NSArray *alphaArray;
    @property (strong, nonatomic) NSArray *ThrdArray;

    @end

Speak Your Mind

*

css.php
Privacy Policy