これは本当におかしくて変です。エラーは次のとおりです。
***** キャッチされない例外 '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 のおかげで、制約が適切に削除されていないことがわかりました。constraints
off のプロパティを使用してthirdPartyView
も、親ビューに保存されている制約は含まれません。この構文を使用する必要がありましたが、これを行うにはもっと短い方法があると思います。
for (NSLayoutConstraint *constraint in self.contentWrapperView.constraints) {
if (constraint.firstItem == self.thirdPartyAnswerView || constraint.secondItem == self.thirdPartyAnswerView) {
[constraints addObject:constraint];
}
}
[self.contentWrapperView removeConstraints:constraints];