0

ユーザーが最初のコンポーネントを選択すると、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 (「果物」のインデックス) のままになる場合があります。

これは競合状態が原因だと思いますが、どうすれば解決できますか?

4

1 に答える 1

0

コンポーネントが 3 つのメンバー (航空会社) を持つ配列を表し、そのコンポーネントで選択された行が最後のメンバーである場合にクラッシュします。その後、コンポーネントを裏返して 2 つのメンバー配列 (果物) を表します。pickerview はこの変数 (selectedrowincomponent:x) を保持しており、2 つのメンバー配列 (メンバー #0-1 のみを持つ) でメンバー #2 を表現しようとしています -> NSRangeException。reload ..で別の配列にフリップする前に、そのコンポーネントのselectedRowを変更する必要があります。

個人的には、1 つのピッカーを使用して 2 つのことを行うのは好きではありません。面倒です。それぞれのデリゲート/データソースになるように別のクラスを作成し、一方を他方のサブクラスにすることができ、必要に応じてそれらを遅延ロードします。

于 2014-01-26T16:52:11.940 に答える