iOS custom UIPickerView with Multiple Components

UIPickerView lets a user select values with rotating wheels much like a casino slot machine. UIDatePicker is a pre-populated UIPickerView to let the user choose date and time. UIPickerViewDataSource and UIPickerViewDelegate are needed to provide the information necessary to create the picker view such as how many components to display, how many rows for each component and the display data. In this example we create a custom UIPicker View with 2 components for ordering Pizza where the user can choose the size and the topping.
iOS custom UIPickerView Pizza Selection
iOS custom UIPickerView with Multiple Components
iOS custom UIPickerView with Multiple Columns
Create a new Project to create an iOS application with template as Empty Application. In the Product Name and Class prefix enter "MyCustomPicker". Check the box "Use Automatic Reference Counting" (ARC) and then choose where you want to create your project.
iOS custom UIPickerView Project

Interface file for the application delegate - MyCustomPickerAppDelegate.h

#import <UIKit/UIKit.h>
#import "MyCustomPickerViewController.h"

@interface MyCustomPickerAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navigationController;
@property (strong, nonatomic) MyCustomPickerViewController *myViewController;

@end

Implementation file for the application delegate - MyCustomPickerAppDelegate.h

#import "MyCustomPickerAppDelegate.h"

@implementation MyCustomPickerAppDelegate
@synthesize navigationController,myViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    
    //create the navigation controller and add to the view
    navigationController = [[UINavigationController alloc] init];
    [self.window addSubview:[self.navigationController view]];
    
    //check if the my viewcontroller eixsts, otherwise create it
    if(self.myViewController == nil)
    {
        MyCustomPickerViewController *myView = [[MyCustomPickerViewController alloc] init];
        self.myViewController = myView;
    }
    
    //push the viewcontroller into the navigation viewcontroller stack
    [self.navigationController pushViewController:self.myViewController animated:YES];
    
    [self.window makeKeyAndVisible];
    return YES;

}

- (void)applicationWillResignActive:(UIApplication *)application{
    //do nothing
}

- (void)applicationDidEnterBackground:(UIApplication *)application{
    //do nothing
}

- (void)applicationWillEnterForeground:(UIApplication *)application{
    //do nothing
}

- (void)applicationDidBecomeActive:(UIApplication *)application{
    //do nothing
}

- (void)applicationWillTerminate:(UIApplication *)application{
    //do nothing
}

@end

Interface file for view controller - MyCustomPickerViewController.h

#import <UIKit/UIKit.h>

@interface MyCustomPickerViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>

@property (nonatomic, strong) UIButton *myButton;
@property (nonatomic, strong) NSArray *size, *topping;
@property (nonatomic, strong) UIPickerView *myCustomPicker;
@property (nonatomic, strong) UIBarButtonItem *doneButton;
@property (nonatomic, strong) UILabel *myLabel;

@end

Implementation file for view controller - MyCustomPickerViewController.m

#import "MyCustomPickerViewController.h"

@interface MyCustomPickerViewController ()

@end

@implementation MyCustomPickerViewController

@synthesize myButton;
@synthesize size, topping;
@synthesize myCustomPicker;
@synthesize doneButton;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];

    self.navigationItem.title = @"Custom Picker";
    
    //create a rounded rectangle type button
    self.myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.myButton.frame = CGRectMake(60.0f, 20.0f, 200.0f, 37.0f);
    [self.myButton setTitle:@"Click here to make PIZZA"
                   forState:UIControlStateNormal];
    [self.myButton addTarget:self
                      action:@selector(chooseMyPizza:)
            forControlEvents:UIControlEventTouchUpInside];
    [self.myButton setTag:1];
    [self.view addSubview:self.myButton];
    
    //create the frame that will contain our label
    CGRect labelFrame = CGRectMake(10.0f, 75.0f, 300.0f, 50.0f);
    //create the label that will display our selection
    self.myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    self.myLabel.text = @"You haven't decided your Pizza...";
    self.myLabel.font = [UIFont boldSystemFontOfSize:16.0f];
    self.myLabel.textAlignment =  NSTextAlignmentLeft;
    self.myLabel.numberOfLines = 0;
    [self.view addSubview:self.myLabel];
    
    //set our picker array data for pizza size and topping
    self.size = [[NSArray alloc] initWithObjects:
                 @"Small",
                 @"Medium",
                 @"Large",
                 @"Extra Large",
                 nil];
    self.topping = [[NSArray alloc] initWithObjects:
                    @"Pepperoni",
                    @"Sausage",
                    @"Bacon",
                    @"Chicken",
                    nil];
    
    
}

//method to call when the "Done" button is clicked
- (void) selectedPizza:(id)sender {
    
    //remove the "Done" button in the navigation bar
 self.navigationItem.rightBarButtonItem = nil;
 
    //which row number is selected for the pizza size
    NSInteger sizeRow = [self.myCustomPicker selectedRowInComponent:0];
    //which row number is selected for the pizza topping
    NSInteger toppingRow = [self.myCustomPicker selectedRowInComponent:1];
    
    //find the pizza size based on the array index
    NSString *whatSize = [self.size objectAtIndex:sizeRow];
    //find the pizza topping based on the array index
    NSString *whatTopping = [self.topping objectAtIndex:toppingRow];
    
    //your selection for the pizza
    NSString *myPizza = [[NSString alloc] initWithFormat:
                         @"Your selected %@ pizza with %@ topping.",whatSize, whatTopping];
    //set the label text with your selection
    self.myLabel.text = myPizza;
    
    //remove my custom picker view form the super view
    [self.myCustomPicker removeFromSuperview];
    
}


- (void) chooseMyPizza:(UIButton *)paramSender{
    
    NSLog(@"Button was clicked, lets select our Pizza");
    
    //if date picker doesn't exists then create it
    if(self.myCustomPicker == nil){
        self.myCustomPicker = [[UIPickerView alloc] init];
        
        //set the picker data source
        self.myCustomPicker.dataSource = self;
        //set the picker delegate
        self.myCustomPicker.delegate = self;
        //display the selection bar
        self.myCustomPicker.showsSelectionIndicator = YES;
    }
    
    //find the current view size
    CGRect screenRect = [self.view frame];
    NSLog(@"Screen frame %f %f", screenRect.origin.y, screenRect.size.height);
    
    //find the custom picker size
    CGSize pickerSize = [self.myCustomPicker sizeThatFits:CGSizeZero];
    
    //set the picker frame
    CGRect pickerRect = CGRectMake(0.0,
                                   screenRect.origin.y + screenRect.size.height - pickerSize.height,
                                   pickerSize.width,
                                   pickerSize.height);
    self.myCustomPicker.frame = pickerRect;
    
    //add the picker to the view
    [self.view addSubview:self.myCustomPicker];
    
    //create the navigation button if it doesn't exists
    if(self.doneButton == nil){
        self.doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                    style:UIBarButtonItemStylePlain
                                                    target:self
                                                    action:@selector(selectedPizza:)];
    }
    //add the "Done" button to the right side of the navigation bar
    self.navigationItem.rightBarButtonItem = self.doneButton;

    
}

// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    
    NSInteger result = 0;
    if ([pickerView isEqual:self.myCustomPicker]){
        result = 2;
    }
    return result;
}

// returns the number of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component{
    
    NSInteger result = 0;
    if ([pickerView isEqual:self.myCustomPicker]){
        switch (component) {
            case 0:
                result = [self.size count];
                break;
            case 1:
                result = [self.topping count];
                break;
                
            default:
                break;
        }
    }
    return result;
    
}

//return a plain NSString to display the row for the component.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row
            forComponent:(NSInteger)component{
    NSString *result = nil;
    if ([pickerView isEqual:self.myCustomPicker]){
        switch (component) {
            case 0:
                result = [self.size objectAtIndex:row];
                break;
            case 1:
                result = [self.topping objectAtIndex:row];
                break;
                
            default:
                break;
        }

    }
    return result;
}


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

@end

Reference