views:

529

answers:

1

Hi! Can anyone help me how to make the UIPickerView displays the first row's value after the last row's value, just like the UIDatePicker where after 12 the 1 will follow.

Thanks

+3  A: 

I don't think its possible to really make it circular, but you can fake it.

#define kRowsInPicker 10000

- (void)viewDidLoad {
    NSArray *localPickerData = [[NSArray alloc] initWithObjects:
           @"Ottawa", @"Toronto", @"Montreal", @"Winnipeg",
           @"Saskatchewan", @"Iqaluit", @"Edomonton", nil];
    [self setPickerData:localPickerData];
    [localPickerData release];

    UIPickerView *localPicker = [[UIPickerView alloc] initWithFrame:
            CGRectMake(0, 0, 320, 216)];
    [localPicker setDelegate:self];
    [localPicker setDataSource:self];
    localPicker.showsSelectionIndicator = YES;
    NSInteger  selectedRow = 0;
    [localPicker selectRow:(((NSInteger)((kRowsInPicker / 2) / [pickerData count])) * [pickerData count]) + (selectedRow%[pickerData count]) inComponent:0 animated:NO];
    [self setPicker:localPicker];
    [localPicker release];

    [[self view] addSubview:picker];
    [super viewDidLoad];
}
#pragma mark -
#pragma mark UIPickerViewDataSource methods

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView
           numberOfRowsInComponent:(NSInteger)component {
    // usually "return [pickerData count];"
    return kRowsInPicker; // 10,000 is good, if you add a few more zeros
                          // there seems to be problems.
}

#pragma mark -
#pragma mark UIPickerViewDelegate methods

- (NSString *)pickerView:(UIPickerView *)pickerView
       titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    return [pickerData objectAtIndex:row%[pickerData count]];
}

You can change the number of strings in pickerData and it will still work fine. The selected row selects the "first" value closest to the middle. row%[pickerData count] returns the following assuming there are 3 NSStrings in pickerData:

ROW             RETURNS
 0                0
 1                1
 2                2
 3                0
 4                1
 5                2
 6                0
 7                1
 8                2
 etc...
It will just cycle 0 through the length of the array. The confusing stuff in viewDidLoad just picks a value as close to the middle as possible using the index of the item of the array you provide in selectedItem. There is no performance hit or memory leak, all you have allocated is the single array. Whenever you access their selected choice, use ([localPicker selectedRowInComponent:0]%[pickerData count]). If there's something you don't understand or something I missed, please comment. Hope this helped!

Mk12
Thanks for the response. But does it will create 1000000 rows, and if I add UIImages to this row does it will create memory/performance issue.
edie
Only the rows that are visible will be loaded, and the cells/rows/whatever they're called for UIPickerViews should be reused, I believe.
Toon Van Acker
Yes, there will be no memory/performance issue.
Mk12
Actually, the performance will be exactly the same (unless you count the calculation of row%[pickerData count] as a performance hit).
Mk12