A.K.C.F.L
A.K.C.F.L

Reputation: 45

UIPickerView crash

I feel my code is logic and i found many example to refer to before doing this but i still couldn't solve this problem. there are more codes but i included only the ones that i think might be related. i did two components pickerview on an actionsheet. the pickerview was supposed to show the cities in second component according to the state selected from the first component.it works good with Johor and Kedah but when it goes to kelantan and melaka state, it crashes. i have a doubt that it relates with the number of items. but i don't know how to solve it. any suggestion? (let me know if more codes needed, will provide it) thank you in advance.

some of the codes: (i included numberOfRowsInComponent,titleForRow and didSelectRow methods and the arrays)

StateList  = [NSArray arrayWithObjects: @"Johor",@"Kedah",@"Kelantan",@"Wilayah Persekutuan",@"Melacca", nil];

JohorCityList = [[NSMutableArray alloc] initWithObjects: @"Kota Tinggi",@"Larkin Lama",@"Muar",@"Pasir Gudang", nil];

KedahCityList = [[NSArray alloc] initWithObjects: @"Langkawi",@"Alor Setar",@"Bakar Arang", nil];

KelantanCityList = [[NSMutableArray alloc] initWithObjects:@"Tanah Merah",@"Kota Bharu", nil];

KLCityList = [[NSArray alloc] initWithObjects: @"Batu Muda", @"Labuan",@"Putrajaya",@"Cheras", nil];

MelaccaCityList = [NSArray arrayWithObjects: @"Bandaraya Melaka", @"Bukit Rambai", nil];

(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) {
    return [StateList count];
}
else if (component == 1){
    if ([selectedState isEqualToString:@"Johor"]) {
        return [JohorCityList count];
    }
    else if ([selectedState isEqualToString:@"Kedah"]){
        return [KedahCityList count];
    }
    else if ([selectedState isEqualToString:@"Kelantan"]) {
        return [KelantanCityList count];
    }
    else if ([selectedState isEqualToString:@"Wilayah Persekutuan"]) {
        return [KLCityList count];
    }
    else if ([selectedState isEqualToString:@"Melacca"]){
        return [MelaccaCityList count];
    }
 //   else
    //    return [JohorCityList count];
}
return [JohorCityList count];}

(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
 if (component == 0) {
    return [StateList objectAtIndex:row];
}
else if (component == 1){
    if ([selectedState isEqualToString:@"Johor"]) {
        return [JohorCityList objectAtIndex:row];
    }
    else if ([selectedState isEqualToString:@"Kedah"]){
        return [KedahCityList objectAtIndex:row];
    }
    else if ([selectedState isEqualToString:@"Kelantan"]) {
        return [KelantanCityList objectAtIndex:row];
    }
    else if ([selectedState isEqualToString:@"Wilayah Persekutuan"]) {
        return [KLCityList objectAtIndex:row];
    }
    else if ([selectedState isEqualToString:@"Melacca"]) {
        return [MelaccaCityList objectAtIndex:row];
    }      
}
return [JohorCityList objectAtIndex:row];}

(void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

NSLog(@"Selected Row %d", row);

    if ([thePickerView selectedRowInComponent:0] == 0){ //JB
        NSLog(@"case 0");
        [thePickerView reloadComponent:1];
        switch (component) {

            case 0:
               selectedState = [StateList objectAtIndex:row];
                return;

            case 1:

               selectedJohorCity =  [JohorCityList objectAtIndex:row];
                return;

        } // end switch

    } // end 

    else if ([thePickerView selectedRowInComponent:0] == 1){ //Kedah
        NSLog(@"case 1");
        [thePickerView reloadComponent:1];
        switch (component) {

            case 0:
                selectedState =  [StateList objectAtIndex:row];
                return;

            case 1:
               selectedKedahCity = [KedahCityList objectAtIndex:row];
                return;

        } // end switch

    } // end 
    else if ([thePickerView selectedRowInComponent:0] == 2){ //Kelantan
        NSLog(@"case 2");
        [thePickerView reloadComponent:1];
        switch (component) {

            case 0:
                selectedState =  [StateList objectAtIndex:row];
                return;

            case 1:
                selectedKelantanCity = [KelantanCityList objectAtIndex:row];

                return;

        } // end switch

    } // end

output:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM    objectAtIndex:]: index 2 beyond bounds [0 .. 1]'

and SIGABRT stops at titleforRow method at:

return [KelantanCityList objectAtIndex:row];

Upvotes: 0

Views: 1676

Answers (2)

Toseef Khilji
Toseef Khilji

Reputation: 17409

It is crash Because You have 2 item in KelantanCityList array and you are trying to access 3rd object of array.

UPdate

For More Dynamic you can use two array one with StateNames and second with Array of City's Array , You can show following Implementation:

ViewDidLoad

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
StateList  = [NSMutableArray  array];
StateNames= [[NSMutableArray alloc]initWithObjects:@"Johor",@"Kedah",@"Kelantan",@"Wilayah Persekutuan",@"Melacca", nil];

JohorCityList = [[NSMutableArray alloc] initWithObjects: @"Kota Tinggi",@"Larkin Lama",@"Muar",@"Pasir Gudang", nil];

KedahCityList = [[NSMutableArray alloc] initWithObjects: @"Langkawi",@"Alor Setar",@"Bakar Arang", nil];

KelantanCityList = [[NSMutableArray alloc] initWithObjects:@"Tanah Merah",@"Kota Bharu", nil];

KLCityList = [[NSMutableArray alloc] initWithObjects: @"Batu Muda", @"Labuan",@"Putrajaya",@"Cheras", nil];

MelaccaCityList = [[NSMutableArray  alloc ]initWithObjects: @"Bandaraya Melaka", @"Bukit Rambai", nil];

selectedState=@"Johor";



[PickerView reloadAllComponents];



[StateList addObject:JohorCityList];
[StateList addObject:KedahCityList];
[StateList addObject:KelantanCityList];
[StateList addObject:KLCityList];
[StateList addObject:MelaccaCityList];

}

Picker DelegateMethod

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

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if (component == 0) {
        return [StateList count];
    }
    {

       int r= [[StateList objectAtIndex:[pickerView selectedRowInComponent:0]]count];
        return  r;
    }


}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if (component == 0) {
        return  [StateNames objectAtIndex:row];
    }
    else
    {
    return   [[StateList objectAtIndex:[pickerView selectedRowInComponent:0]]objectAtIndex:row];

    }
    return   @"";
}

-(void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    if (component==0)
    {
        [thePickerView reloadComponent:1];

    }
    else
    {
        NSLog(@"selected State:%@ ", [StateNames objectAtIndex:[thePickerView selectedRowInComponent:0]]);
        NSLog(@"selcted city:%@",[[StateList objectAtIndex:[thePickerView selectedRowInComponent:0]]objectAtIndex:row]);
    }

}

Upvotes: 2

Julian
Julian

Reputation: 9337

This basically means that you are trying to get object out of bounds for KelantanCityList. You are trying to get element at index 2 while the array has only 2 elements (last index in array is 1).

You should debug it and see what is going on, it might be a bad value for selectedState which causes that you are trying to retrieve data from the wrong array. For sure checking whether index you will try to refer from array is not out of bound will help you to avoid a crash but it will not solve the basic problem which might be setting improperly value for selectedState.

Upvotes: 1

Related Questions