这个实在是太诡异了。这是错误:
***** 由于未捕获的异常“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
关闭的属性thirdPartyView
不包括存储在父视图上的约束。不得不使用这种语法,虽然我猜有一个更短的方法来做到这一点:
for (NSLayoutConstraint *constraint in self.contentWrapperView.constraints) {
if (constraint.firstItem == self.thirdPartyAnswerView || constraint.secondItem == self.thirdPartyAnswerView) {
[constraints addObject:constraint];
}
}
[self.contentWrapperView removeConstraints:constraints];