1

2 つのテキスト フィールド (カテゴリ、サブカテゴリ) を含む画面があり、それぞれがカスタム UIPickerView に接続されています。サブカテゴリ ビューに表示されるオプションは、最初のフィールドの値として選択されたカテゴリによって異なります。

ユーザーがカテゴリを選択していない場合、サブカテゴリ フィールドを選択すると、標準キーボードが表示されます (この動作は問題ありません)。

ユーザーがカテゴリを選択してからサブカテゴリ フィールドを操作すると、すべて正常に機能します。

この問題は、ユーザーがカテゴリを入力し、サブカテゴリ ピッカーを起動してから、戻ってカテゴリ フィールドをクリアしたときに発生します。この時点で、ユーザーがサブカテゴリ フィールドを選択すると、ピッカーはデータなしで表示され、それを操作するとアプリがクラッシュします。

エラーテキスト:

*** Assertion failure in -[UITableViewRowData rectForRow:inSection:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableViewRowData.m:1630
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for rect at invalid index path (<NSIndexPath 0x719eb60> 2 indexes [0, 0])'
*** First throw call stack:
(0x1cc3012 0x1100e7e 0x1cc2e78 0xb96665 0x22df20 0xf12de 0x481086 0x480f7a 0xa440d 0xa69eb 0x30f85a 0x30e99b 0x3100df 0x312d2d 0x312cac 0x30aa28 0x77972 0x77e53 0x55d4a 0x47698 0x1c1edf9 0x1c1ead0 0x1c38bf5 0x1c38962 0x1c69bb6 0x1c68f44 0x1c68e1b 0x1c1d7e3 0x1c1d668 0x44ffc 0x2acd 0x29f5)
libc++abi.dylib: terminate called throwing an exception

これが私のコードです:

- (IBAction)showYourPicker:(id)sender {
        isCategoryPicker = true;
        // create a UIPicker view as a custom keyboard view
        UIPickerView* pickerView = [[UIPickerView alloc] init];
        [pickerView sizeToFit];
        pickerView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
        pickerView.delegate = self;
        pickerView.dataSource = self;
        pickerView.showsSelectionIndicator = YES;
        self.catPickView = pickerView;  //UIPickerView

        categoryField.inputView = pickerView;

        // create a done view + done button, attach to it a doneClicked action, and place it in a toolbar as an accessory input view...
        // Prepare done button
        UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
        keyboardDoneButtonView.barStyle = UIBarStyleBlack;
        keyboardDoneButtonView.translucent = YES;
        keyboardDoneButtonView.tintColor = nil;
        [keyboardDoneButtonView sizeToFit];

        UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                                        style:UIBarButtonItemStyleBordered target:self
                                                                       action:@selector(pickerDoneClicked:)];

        [keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];

        // Plug the keyboardDoneButtonView into the text field...
        categoryField.inputAccessoryView = keyboardDoneButtonView;
    }

    - (IBAction)showYourSubPicker:(id)sender {
        isCategoryPicker = false;
        WCSharedCache *sharedManager = [WCSharedCache sharedManager];
        BOOL iLLAllowIt = false;
        for(int i = 0; i < [sharedManager.categories count]; i++) {
            if([[[sharedManager categories] objectAtIndex:i] isEqualToString:[categoryField text]]) {
                iLLAllowIt = true;
            }
        }
        if(!iLLAllowIt) {
            return;
        }
        // create a UIPicker view as a custom keyboard view
        UIPickerView* pickerView = [[UIPickerView alloc] init];
        [pickerView sizeToFit];
        pickerView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
        pickerView.delegate = self;
        pickerView.dataSource = self;
        pickerView.showsSelectionIndicator = YES;
        self.subCatPickView = pickerView;  //UIPickerView

        subcategoryField.inputView = pickerView;

        // create a done view + done button, attach to it a doneClicked action, and place it in a toolbar as an accessory input view...
        // Prepare done button
        UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
        keyboardDoneButtonView.barStyle = UIBarStyleBlack;
        keyboardDoneButtonView.translucent = YES;
        keyboardDoneButtonView.tintColor = nil;
        [keyboardDoneButtonView sizeToFit];

        UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                                       style:UIBarButtonItemStyleBordered target:self
                                                                      action:@selector(pickerDoneClicked:)];

        [keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];

        // Plug the keyboardDoneButtonView into the text field...
        subcategoryField.inputAccessoryView = keyboardDoneButtonView;
    }

    - (void) pickerDoneClicked: (id) picker {
        if(isCategoryPicker) {
            [categoryField resignFirstResponder];
        } else {
            [subcategoryField resignFirstResponder];
        }
    }

    - (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
        WCSharedCache *sharedManager = [WCSharedCache sharedManager];
        if(isCategoryPicker) {
            [categoryField setText:[[sharedManager categories] objectAtIndex:row]];
        } else {
            @try {
                int idx = 0;
                for(int i = 0; i < [sharedManager.categories count]; i++) {
                    if([[[sharedManager categories] objectAtIndex:i] isEqualToString:[categoryField text]]) {
                        idx = i;
                        break;
                    }
                }
                [subcategoryField setText:[[[sharedManager subcategories]objectAtIndex:idx] objectAtIndex:row]];
            } @catch (NSException *e) {
                NSLog(@"Exception: %@",e);
               [subcategoryField setText:@"" ];
            }
        }
    }

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

    - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
    {
        WCSharedCache *sharedManager = [WCSharedCache sharedManager];
        if(isCategoryPicker) {
            return [[sharedManager categories]count];
        } else {
            for(int i = 0; i < [sharedManager.categories count]; i++) {
                if([[[sharedManager categories] objectAtIndex:i] isEqualToString:[categoryField text]]) {
                    return [[[sharedManager subcategories] objectAtIndex:i] count];
                }
            }
        }
        return 0;
    }

    - (NSString *)pickerView: (UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component
    {
        WCSharedCache *sharedManager = [WCSharedCache sharedManager];
        if(isCategoryPicker) {
            return [[sharedManager categories] objectAtIndex:row];
        } else {
            for(int i = 0; i < [sharedManager.categories count]; i++) {
                if([[[sharedManager categories] objectAtIndex:i] isEqualToString:[categoryField text]]) {
                    return [[[sharedManager subcategories] objectAtIndex:i] objectAtIndex:row];
                }
            }
        }
        return @"";
    }

実装できる方法、トライキャッチ、元のキーボードの復活、またはデータがない場合にユーザーがこのフィールドにアクセスできないようにすることができる場所はありますか。カテゴリのデータは NSArray にあります。サブカテゴリのデータは、関連付けられたカテゴリのインデックスからインデックスが作成された 2 次元の NSArray にあります。

4

1 に答える 1

0

次のデフォルト値を変更してこの問題を修正した場合:

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
    {
        WCSharedCache *sharedManager = [WCSharedCache sharedManager];
        if(isCategoryPicker) {
            return [[sharedManager categories]count];
        } else {
            for(int i = 0; i < [sharedManager.categories count]; i++) {
                if([[[sharedManager categories] objectAtIndex:i] isEqualToString:[categoryField text]]) {
                    return [[[sharedManager subcategories] objectAtIndex:i] count];
                }
            }
        }
        return 1;
    }

ゼロから 1 へ。コンポーネントの行数が 0 の場合、UIPickerView (少なくとも上記の実装では) は例外をスローせずにスクロールを処理できないようです。Apple の UIPickerView クラスのドキュメントによると、このメソッドのデフォルト値は0.

于 2013-10-15T17:30:02.867 に答える