A custom, configurable, horizontal version of UIPickerView built to live in a UITableViewCell.
Objective-C Ruby



A custom, configurable, horizontal version of UIPickerView.

Also included is CPPickerViewCell, a UITableViewCell sublcass that adds a CPPickerView to the right side of the cell. This cell was envisioned for a settings-type view, allowing a multi-option setting to be handled in a single table row (whereas normally it would require a disclosure or multiple rows).

If you're interested in a vertical custom UIPickerView controller, check out AFPickerView by Arkady Fraerman! This code is essentially forked from his project.

CPPickerView screenshot

CPPickerView is currently in use by at least one approved app in the App Store (Hipmunk for iPhone/iPad!).



To customize the appearance, replace the following images with your own:

  • wheelBackground.png
  • stretchableGlass.png
  • shadowOverlay.png

NOTE: CPPickerView uses - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets (for iOS 5.0 and up) or - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets (for below iOS 5.0) to stretch wheelBackground.png and stretchableGlass.png. Be sure to look at the sample images in relation to the cap sizes set in CPPickerView.m's initWithFrame: before changing the sizing of the images, as you may need to adjust the caps. shadowOverlay.png is currently simply stretched to fit the frame.

Several appearance options are settable via properties:

  • BOOL showGlass - defines whether or not to show the "glass" overlay over the selected item.
  • UIEdgeInsets peekInset - defines the amount the item to the left and right of the currently selected item "peek" into view. This can be used as an indication to the user that there are other items, if desired. NOTE: You most likely want to leave the top and bottom inset values at 0, and adjust the left and right values. Larger inset values mean more peek.

You can also enable/disable the ability for the user to change the picker via the enabled property. The default state is YES.

Standard Usage

Create a CPPickerView instance and configure it:

pickerView = [[CPPickerView alloc] initWithFrame:CGRectMake(30.0, 250.0, 126.0, 197.0)];
pickerView.rowFont = [UIFont boldSystemFontOfSize:19.0];
pickerView.rowIndent = 10.0;
pickerView.showGlass = YES;

Set the dataSource, delegate, and call [pickerView reloadData]:

pickerView.dataSource = self;
pickerView.delegate = self;
[pickerView reloadData];

Then implement CPPickerViewDataSource and CPPickerViewDelegate in your controller.

CPPickerViewCell Usage

Use CPPickerViewCell like a normal UITableViewCell. Inside tableView:cellForRowAtIndexPath:, dequeue or create the cell:

CPPickerViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[CPPickerViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

Set the data source and the delegate for the cell, and inform it of it's index path:

cell.dataSource = self;
cell.delegate = self;
cell.currentIndexPath = indexPath;

NOTE: CPPickerViewCells MUST be informed of their index path in the table, or you won't be able to distinguish between them in your datasource and delegate methods!

And implement CPPickerViewCellDataSource and CPPickerViewCellDelegate per the protocols. In the included example the TableViewController (i.e. self) is set up as the data source and delegate for all cells.

The data source/delegate methods for CPPickerViewCell convert the normal CPPickerView data source/delegate methods to refer to the requests for data by NSIndexPath rather than the CPPickerView object (to match the typical way table cells are identified).

Finally, reload the cell (aka the CPPickerView, the items in the picker will be requested again) and then reconfigure it with any specific settings for the given row if you're recalling some previously stored settings. Then return the cell.

[cell reloadData];
// Reconfigure
cell.showGlass = YES;
cell.peekInset = UIEdgeInsetsMake(0, 18, 0, 18);
NSInteger *storedSelectedIndex = [[AnArrayOfStoredStuff objectAtIndex:indexPath.row] intValue];
[cell selectItemAtIndex:storedSelectedIndex animated:NO];  //Unanimated, because this should be immediate
return cell;


  • Any ideas?


Charles Powell

Give me a shout if you're using this in your project!