objective-cuipickerviewnsrangeexception

NSRangeException when I have multiple pickerViews for multiple textfields


#import "ProfileViewController.h"

@implementation ProfileViewController{
    NSArray *currentArray;
    UITextField *currentTextField;
}

@synthesize picker, Feets, Inchs, Weights, Months, Days, Years, HeightValue, WeightValue, DOBValue;
@synthesize scrollView;
int variabla;

// Control the textfield go up when tap the textfield and keyboard coming out
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
    [textField resignFirstResponder];
    [picker setHidden:YES];
    currentTextField = textField;
    NSLog(@"222222");
    if (currentTextField == HeightValue)
    {
        NSLog(@"3333333");
        [HeightValue resignFirstResponder];
        [picker setHidden:NO];
        variabla = 1;
    }
    else if (currentTextField == WeightValue)
    {
        NSLog(@"4444444");
        [WeightValue resignFirstResponder];
        [picker setHidden:NO];
        variabla = 2;
    }
    else if (currentTextField == DOBValue){
        NSLog(@"5555555");
        [DOBValue resignFirstResponder];
        [picker setHidden:NO];
        variabla = 3;
    }
    NSLog(@"variabla %d",variabla);
    [picker reloadAllComponents];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"111111");
 NSString *path = [[NSBundle mainBundle]pathForResource:@"WeightList" ofType:@"plist"];
    Weights = [[NSMutableArray alloc]initWithContentsOfFile:path];

    [picker setHidden:YES];

 Feets = [[NSMutableArray alloc]initWithObjects:@"0ft", @"1ft", @"2ft", @"3ft", @"4ft", @"5ft", @"6ft", @"7ft", @"8ft", @"9ft",nil];
    Inchs = [[NSMutableArray alloc]initWithObjects:@"0in", @"1in", @"2in", @"3in", @"4in", @"5in", @"6in", @"7in", @"8in", @"9in", @"10in", @"11in",nil];
    Months = [[NSMutableArray alloc]initWithObjects:@"1", @"2", @"3",nil];
    Days = [[NSMutableArray alloc]initWithObjects:@"1", @"2", @"3",nil];
    Years = [[NSMutableArray alloc]initWithObjects:@"1", @"2", @"3",nil];


#pragma mark - UIPcikerView DataSource and Delegate method
    // returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    if (variabla == 1){
        return 2;
    }
    else if (variabla == 2){
        return 1;
    }
    else
        return 3;
}

    // returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    if (variabla == 1){
        if (component == feetComponent)
            return [Feets count];
        if (component == inchComponent)
            return [Inchs count];
    }
    if (variabla == 2){
        return [Weights count];
    }
    else{
        if (component == monthComponent)
            return [Months count];
        if (component == dayComponent)
            return [Days count];
        else
            return [Years count];
    }
}


  // set the row text to the textfield
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED{
    if (variabla == 1){
        if (component == feetComponent)
            return Feets[row];
        if (component == inchComponent)
            return Inchs[row];
    }
    if (variabla == 2){
        return Weights[row];
    }
    else{
        if (component == monthComponent)
            return Months[row];
        if (component == dayComponent)
            return Days[row];
        else
            return Years[row];
    }
}


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component __TVOS_PROHIBITED{
    if (currentTextField == HeightValue){
        NSInteger feetRow = [picker selectedRowInComponent:feetComponent];
        NSInteger inchRow = [picker selectedRowInComponent:inchComponent];
        NSString *feet = Feets[feetRow];
        NSString *inch = Inchs[inchRow];
        NSString *msg = [[NSString alloc]initWithFormat:@"%@ %@", feet, inch];
        HeightValue.text = msg;
    }
    if (currentTextField == WeightValue){
        NSInteger weightRow = [picker selectedRowInComponent:weightComponent];
        NSString *weight = Weights[weightRow];
        NSString *msg2 = [[NSString alloc]initWithFormat:@"%@",weight];
        WeightValue.text = msg2;
    }
    if (currentTextField == DOBValue){
        NSInteger monthRow = [picker selectedRowInComponent:monthComponent];
        NSInteger dayRow = [picker selectedRowInComponent:dayComponent];
        NSInteger yearRow = [picker selectedRowInComponent:yearComponent];
        NSString *month = Months[monthRow];
        NSString *day = Days[dayRow];
        NSString *year = Years[yearRow];
        NSString *msg3 = [[NSString alloc]initWithFormat:@"%@ / %@ / %@", month, day, year];
        WeightValue.text = msg3;
    }

}

@end

Above is the .m file code. When I run the simulator, the first textfield for the Height is working fine, but in the Weight and Date textfield, the picker view got the exception.

Simulator screen shot

NSRangeException screen shot


Solution

  • Well the exception says Index 5 beyond bounds [0..0]. So that says you have an array of size 1 but are asking it for the object at index 5, which doesn't make sense, so it crashes.

    The traceback says that objectAtIndex method is being called from selectedRowInComponent:, which is being called from your didSelectRow:inComponent. So that suggests that you're passing an invalid component number to selectedRowInComponent.

    I don't know where weightComponent and month/day/yearComponent are being set, but I'm guessing that they are not being set to 0 and 0, 1, and 2 respectively.

    As an aside, I would also add that when you have a picker with labels 0ft, 1ft etc, that you don't keep around all these tables. Instead of creating a table and indexing it, just answer the titleForRow call with return [NSString stringWithFormat:@"%dft",row];