0

I have a two level UIPickerView which means if user selects the first component, the second component will update its data.

The data should be look like this:

self.type = @[@"fruit", @"airlines"];
self.data = @[@[@"Apple", @"Orange"], @[@"Delta", @"United", @"American"]];

datasource and delegate method:

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

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    if(component == 0){
        return self.data.count;
    }else if(component == 1){
        NSInteger row1 = [pickerView selectedRowInComponent:0];
        return [self.data[row1] count];
    }
} 


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

    // here may crash, some time
    NSLog(@"data: %@", self.data[row1][row2]);
}


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    if(component == 0){
        return self.type[row];
    }else if(component == 1){
        NSInteger row1 = [pickerView selectedRowInComponent:0];
        // here may also crash
        return self.data[row1][row];
    }
}

There are several places which may cause crashes(NSRangeException) in the above code as commented. However, they rarely happened. I haven't gotten this crash yet, but my users had according to Crashlytics report.

I add some codes to validate row1 and row2 before accessing self.data[row1][row2] and send to my server if fail. I found that the value of [pickerView selectedRowInComponent:0] may be incorrect some time. For example, when user changes the first component from "fruit" to "airlines" and select some item in second component, the value of selectedRowInComponent:0 may still be 0(index of "fruit").

I guess this is caused by race condition but how can I solve this?

4

1 回答 1

0

如果一个组件表示具有三个成员(航空公司)的数组并且该组件中的选定行是最后一个成员,然后将组件翻转以表示两个成员数组(水果),它将崩溃。pickerview 保留了这个变量 (selectedrowincomponent:x),现在想要在两个成员数组上表示成员 #2(只有成员 #0-1)-> NSRangeException。您需要先更改该组件中的 selectedRow,然后再使用 reload 将其翻转到不同的数组。

我个人不喜欢使用一个选择器来做两件事,恕我直言,这很麻烦,只是为每个编写一个不同的类作为委托/数据源,一个可以是另一个的子类,然后根据需要延迟加载 em

于 2014-01-26T16:52:11.940 回答