2

これは本当におかしくて変です。エラーは次のとおりです。

***** キャッチされない例外 'NSGenericException' が原因でアプリを終了しています。理由: 'ビューに制約をインストールできません。制約は、ビューのサブツリーの外部から何かを参照していますか? それは違法です。制約: ビュー:>'**

したがって、カスタム セルにはサブビューがあり、構成ステップで追加されます。つまり、セルを deuque し、データ オブジェクトで構成します。構成ステップで、サードパーティのサブビューが存在しない場合は追加します。

if (!self.thirdPartyAnswerView) {
    self.thirdPartyAnswerView = [TCThirdPartyAPIHelper thirdPartyAnswerViewForThirdPartyAPIServiceType:answer.thirdPartyObject.thirdPartyAPIType];
    self.thirdPartyAnswerView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.contentWrapperView addSubview:self.thirdPartyAnswerView];
    NSDictionary *metrics = @{
                              @"TC_CELL_TOP_PADDING": [NSNumber numberWithFloat:TC_CELL_TOP_PADDING],
                              @"TC_CELL_BOTTOM_PADDING": [NSNumber numberWithFloat:TC_CELL_BOTTOM_PADDING],
                              @"TC_CELL_RIGHT_PADDING": [NSNumber numberWithFloat:TC_CELL_RIGHT_PADDING],
                              @"TC_CELL_LEFT_PADDING": [NSNumber numberWithFloat:TC_CELL_LEFT_PADDING],
                              };
    [self.contentWrapperView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-TC_CELL_LEFT_PADDING-[_thirdPartyAnswerView]-TC_CELL_RIGHT_PADDING-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];
    [self.contentWrapperView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-TC_CELL_TOP_PADDING-[_thirdPartyAnswerView]-TC_CELL_BOTTOM_PADDING-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];
}

これはすべてうまくいきます。実際、それはうまく機能します。回答セル (モーダル編集/作成フローを提示) に進み、終了して同じ画面に戻ります。を呼び出す代わりに、アニメーションを使用して行を適切に更新しますreloadData

画面

既存のデータを取得した後でカテゴリ ボタンを押すと、問題が発生します。カテゴリ選択モーダルを引き上げます。カテゴリを選択すると、前の画面が呼び出さreloadDataれ、カテゴリのモーダルがアニメーション化されます。まあ、少なくともそれがすべきことです。代わりに、アニメーションの開始時にすぐにクラッシュします。問題reloadDataなく鳴るのですが、アニメが始まるとすぐにブーン。上記のクラッシュをスローするか、説明を提供しないか、_supportsContentDimensionVariablesセレクターが間違ったオブジェクトに送信されたという苦情でクラッシュします。

使用されるビューはセルによって異なる可能性があるため、呼び出しprepareForReuseではthirdPartyAnswerView. これを削除してもクラッシュしません(ただし、セルに不要なビューがあります)。前後の制約を削除してみました:

if (self.thirdPartyAnswerView) {
    [self.contentWrapperView removeConstraints:self.thirdPartyAnswerView.constraints];
    [self.thirdPartyAnswerView removeFromSuperview];
    self.thirdPartyAnswerView = nil;
}

それはうまくいきませんでした。この内容を構成セクションから出し入れしようprepareForReuseとしました(新しいサブビューを追加する前にサブビューを削除してください)。それはうまくいきませんでした。私は途方に暮れています。

アップデート

モーダルでカテゴリが選択されたときに呼び出されるコードは次のとおりです。

categorySelectionVC.didTouchCategoryBlock = ^(TCCategory *category) {
    TCQuestionBuilderViewController *sself = weakself;
    sself.category = category;
    [sself.tableView reloadData];
    [sself.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:TableSectionCategory] animated:NO scrollPosition:UITableViewScrollPositionNone];
    [sself dismissViewControllerAnimated:YES completion:^{
    }];
};

私が決定したことはselectRowAtIndexPath、リロード後にビットをコメントアウトすると、正しく機能するということです。私が理解していないのは、その理由です。私はこれを何度も使用しました。データをリロードし、選択したものを再選択して、tableView が再び表示されたときにアニメーションが「オフ」になるようにします。

私は間違っていました。それを削除すると、最初は解決しましたが、モーダルを再度入力してからカテゴリを再度選択すると、クラッシュしました。

解決した

sapi のおかげで、制約が適切に削除されていないことがわかりました。constraintsoff のプロパティを使用してthirdPartyViewも、親ビューに保存されている制約は含まれません。この構文を使用する必要がありましたが、これを行うにはもっと短い方法があると思います。

for (NSLayoutConstraint *constraint in self.contentWrapperView.constraints) {
    if (constraint.firstItem == self.thirdPartyAnswerView || constraint.secondItem == self.thirdPartyAnswerView) {
        [constraints addObject:constraint];
    }
}
[self.contentWrapperView removeConstraints:constraints];
4

1 に答える 1

2

制約は双方向ですが、逆の関係は順の関係とは異なるオブジェクトによって表されます。

たとえば、次を使用して制約を作成する場合:

[self.contentWrapperView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-TC_CELL_LEFT_PADDING-[_thirdPartyAnswerView]-TC_CELL_RIGHT_PADDING-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];

thenself.contentWrapperView_thirdPartyAnswerView両方に制約が追加されていますが、どちらも同じ関係を表していますが、異なるオブジェクトです

電話すると:

[self.contentWrapperView removeConstraints:self.thirdPartyAnswerView.constraints];

self.contentWrapperViewこれは、上の制約と同一self.thirdPartyAnswerViewのすべての制約(つまり、なし)を削除しようとします。

適切な制約を削除するには、配列をループして、 を参照しているものを特定する必要がありますthirdPartyAnswerView(これを行う 1 つの方法については、質問への編集を参照してください)。

于 2013-03-27T21:54:22.990 に答える