Vomarhk Vomarhk - 2 months ago 11
Objective-C Question

How to load data in second component of UIPickerView from first component selection

I have tried to find a solution for my problem for over a week now but no success with other similar questions on this website.

I have multiple NSMutableArrays for my pickerView and I'm trying to set the second component's data based on first component's selection. My main problem is that the second component's data is empty when I select anything other than the first choice in the first component. When the first choice in the first component is selected, I have all my arrays together one after the other in my second component but I want only 1 array per component data.

This is my code in the ViewController.h:

@interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>

{
NSMutableArray *maListeTrier;
NSMutableArray *maListeTypes;
NSMutableArray *maListeSousTypes;
NSMutableArray *maListeSousTypes2;
NSMutableArray *maListeSousTypes3;
NSMutableArray *maListeSousTypes4;
NSMutableArray *maListeSousTypes5;
}

@property NSString *selectedType;
@property NSString *selectedArray;

@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
@property (weak, nonatomic) IBOutlet UILabel *labelType;
@property (weak, nonatomic) IBOutlet UILabel *labelSousType;


And this is my code for ViewController.m:

@synthesize selectedType;
@synthesize selectedArray;

- (void)viewDidLoad {
[super viewDidLoad];
selectedType=[[NSString alloc]init];
selectedArray=[[NSString alloc]init];

maListeTypes = [[NSMutableArray alloc] init];
[maListeTypes addObject:@"Type 1"];
[maListeTypes addObject:@"Type 2"];

maListeSousTypes=[[NSMutableArray alloc]init];
[maListeSousTypes addObject:@"Sous-type 1"];
[maListeSousTypes addObject:@"Sous-type 2"];
[maListeSousTypes addObject:@"Sous-type 3"];
[maListeSousTypes addObject:@"Sous-type 4"];
[maListeSousTypes addObject:@"Sous-type 5"];

maListeSousTypes2=[[NSMutableArray alloc]init];
[maListeSousTypes addObject:@"22222"];
[maListeSousTypes addObject:@"22222"];
[maListeSousTypes addObject:@"22222"];
[maListeSousTypes addObject:@"22222"];
[maListeSousTypes addObject:@"22222"];
}

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

//Méthode pour déterminer le nombre de colonnes dans chaque picker view
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}

//Méthode pour déterminer le nombre de rangées dans chaque picker view
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if(component==0){
return [maListeTypes count];
}
else if(component==1){
if([selectedType isEqualToString:@"Type 1"]){
return [maListeSousTypes count];
}
else if([selectedType isEqualToString:@"Type 2"]){
return [maListeSousTypes2 count];
}
else{
return 0;
}
}
else{
return 0;
}
}

//Méthode pour indiquer quoi afficher comme choix dans chaque picker view
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component==0){
return [maListeTypes objectAtIndex:row];
}
else{
if([selectedType isEqualToString:@"Type 1"]){
return [maListeSousTypes objectAtIndex:row];
}
else{
return [maListeSousTypes2 objectAtIndex:row];
}
}
}

//Méthode pour indiquer quelle action va se produire lorsqu'on clique sur un des choix des picker views
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if(component==0){
selectedType=[maListeTypes objectAtIndex:row];
[pickerView reloadAllComponents];
_labelType.text=[maListeTypes objectAtIndex:[pickerView selectedRowInComponent:0]];
}
else if(component==1){
_labelSousType.text=[maListeSousTypes objectAtIndex:[pickerView selectedRowInComponent:1]];
}
}


When my first component selection is the first choice "Type 1", in my second component I see data from NSMutableArray "maListeSousTypes" and "maListeSousTypes2" one after another like here:
Screenshot

When "Type 2" is selected from the first component, my second component is empty.

phi phi
Answer

This has to be simpler than what you're doing. Let me show you how I did it in a quick example:

@interface ViewController () <UIPickerViewDataSource, UIPickerViewDelegate>

@property (strong, nonatomic) IBOutlet UIPickerView *pickerView;

@property (nonatomic, strong) NSArray *leftComponentItems; // Items from this array will populate the left component
@property (nonatomic, strong) NSArray *rightComponentItemsA; // Items from this array will populate the right component, when the 1st row of the left component is selected
@property (nonatomic, strong) NSArray *rightComponentItemsB; // Items from this array will populate the right component, when the 2nd row of the left component is selected

@property (nonatomic, assign) NSInteger selectedLeftRow; // This keeps track of the selected row on the left component (you could take that from the datasource as well)

@end

and then in your implementation:

@implementation ViewController 

- (void)viewDidLoad {
    [super viewDidLoad];

    self.selectedLeftRow = 0;

    self.leftComponentItems = @[@"first", @"second"];

    self.rightComponentItemsA = @[@"A1", @"A2", @"A3", @"A4", @"A5"];
    self.rightComponentItemsB = @[@"B1", @"B2", @"B3", @"B4", @"B5", @"B6", @"B7"];
}

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 2; // We have left & right components, this will always be "2"
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    if (component == 0) {
        return self.leftComponentItems.count;
    }

    if (component == 1) {
        if (self.selectedLeftRow == 0) {
            return self.rightComponentItemsA.count;
        } else {
            return self.rightComponentItemsB.count;
        }
    }

    return 0;
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {

    if (component == 0) {
        return self.leftComponentItems[row];
    }

    if (component == 1) {
        if (self.selectedLeftRow == 0) {
            return self.rightComponentItemsA[row];
        } else {
            return self.rightComponentItemsB[row];
        }
    }

    return @"default";

}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    if (component == 0) {
        self.selectedLeftRow = row; // We keep track of the selected row
        [pickerView reloadComponent:1]; // When we select a row in the left component, update the data on the right component
    }
}

@end

Feel free to ask if you don't understand something.