ユーザーが最初のコンポーネントを選択すると、2 番目のコンポーネントがそのデータを更新することを意味する 2 レベルの UIPickerView があります。
データは次のようになります。
self.type = @[@"fruit", @"airlines"];
self.data = @[@[@"Apple", @"Orange"], @[@"Delta", @"United", @"American"]];
データソースとデリゲート メソッド:
- (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];
}
}
コメントされているように、上記のコードにはクラッシュ (NSRangeException) を引き起こす可能性のある場所がいくつかあります。しかし、それらはめったに起こりませんでした。このクラッシュはまだ発生していませんが、Crashlytics のレポートによると、私のユーザーはクラッシュしました。
self.data[row1][row2] にアクセスする前に row1 と row2 を検証するコードをいくつか追加し、失敗した場合はサーバーに送信します。[pickerView selectedRowInComponent:0] の値が正しくない場合があることがわかりました。たとえば、ユーザーが最初のコンポーネントを「果物」から「航空会社」に変更し、2 番目のコンポーネントでアイテムを選択すると、selectedRowInComponent:0 の値は 0 (「果物」のインデックス) のままになる場合があります。
これは競合状態が原因だと思いますが、どうすれば解決できますか?