Я пытаюсь включить автомат в свой подкласс UITableViewHeaderFooterView. Класс довольно простой, всего две метки. Это полный подкласс:
@implementation MBTableDetailStyleFooterView
static void MBTableDetailStyleFooterViewCommonSetup(MBTableDetailStyleFooterView *_self) {
UILabel *rightLabel = [[UILabel alloc] init];
_self.rightLabel = rightLabel;
rightLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_self.contentView addSubview:rightLabel];
UILabel *leftLabel = [[UILabel alloc] init];
_self.leftLabel = leftLabel;
leftLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_self.contentView addSubview:leftLabel];
NSDictionary *views = NSDictionaryOfVariableBindings(rightLabel, leftLabel);
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[leftLabel]-(>=10)-[rightLabel]-10-|" options:0 metrics:nil views:views];
[_self.contentView addConstraints:horizontalConstraints];
// center views vertically in super view
NSLayoutConstraint *leftCenterYConstraint = [NSLayoutConstraint constraintWithItem:leftLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[_self.contentView addConstraint:leftCenterYConstraint];
NSLayoutConstraint *rightCenterYConstraint = [NSLayoutConstraint constraintWithItem:rightLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[_self.contentView addConstraint:rightCenterYConstraint];
// same height for both labels
NSLayoutConstraint *sameHeightConstraint = [NSLayoutConstraint constraintWithItem:leftLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:rightLabel attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
[_self.contentView addConstraint:sameHeightConstraint];
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithReuseIdentifier:reuseIdentifier];
MBTableDetailStyleFooterViewCommonSetup(self);
return self;
}
@end
Этот класс используется как нижний колонтитул в первом разделе в таблицеView с двумя разделами. Первый раздел содержит динамические элементы. Второй раздел имеет только одну строку, которая используется для добавления новых элементов в первый раздел.
Если в первом разделе нет элементов, я скрываю footerView. Поэтому, когда я добавляю первый новый элемент, я должен перезагрузить раздел, чтобы появился footerView. Код, который делает все это, выглядит следующим образом:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.section == 1) {
BOOL sectionNeedsReload = ([self.data count] == 0); // reload section when no data (and therefor no footer) was present before the add
[self.data addObject:[NSDate date]];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:[self.data count]-1 inSection:0];
if (sectionNeedsReload) {
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else {
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[self configureFooter:(MBTableDetailStyleFooterView *)[tableView footerViewForSection:0] forSection:0];
}
}
- (void)configureFooter:(MBTableDetailStyleFooterView *)footer forSection:(NSInteger)section {
footer.leftLabel.text = @"Total";
footer.rightLabel.text = [NSString stringWithFormat:@"%d", [self.data count]];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
MBTableDetailStyleFooterView *footer = nil;
if (section == 0 && [self.data count]) {
footer = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Footer"];
[self configureFooter:footer forSection:section];
}
return footer;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = 0;
if (section == 0 && [self.data count]) {
height = 20.0f;
}
return height;
}
Ничего особенного. Тем не менее, , как только reloadSections:withRowAnimations:
вызывается в моем tableView, он выдает исключение, потому что он "не может одновременно удовлетворять ограничениям".
Где-то в таблицеView добавлено ограничение на перенос маски для автоматического изменения размера для моего нижнего колонтитула.
(
"<NSLayoutConstraint:0x718a1f0 H:[UILabel:0x7189130]-(10)-| (Names: '|':_UITableViewHeaderFooterContentView:0x7188df0 )>",
"<NSLayoutConstraint:0x7189e30 H:[UILabel:0x71892c0]-(>=10)-[UILabel:0x7189130]>",
"<NSLayoutConstraint:0x718a0a0 H:|-(10)-[UILabel:0x71892c0] (Names: '|':_UITableViewHeaderFooterContentView:0x7188df0 )>",
"<NSAutoresizingMaskLayoutConstraint:0x7591ab0 h=--& v=--& H:[_UITableViewHeaderFooterContentView:0x7188df0(0)]>"
)
Когда я заменяю reloadSections:withRowAnimations:
на вызов reloadData
, добавляется ограничение авторезистивной маски, и все работает нормально.
Интересно, что исключение говорит мне, что он пытается сломать ограничение <NSLayoutConstraint:0x7189e30 H:[UILabel:0x71892c0]-(>=10)-[UILabel:0x7189130]>
Но когда я записываю ограничения в последующих вызовах на configureFooter:forSection:
, это ограничение все еще существует, но ограничение маски для автоматического изменения размера отсутствует
Ограничения - это именно те, которые я установил.
(
"<NSLayoutConstraint:0x718a0a0 H:|-(10)-[UILabel:0x71892c0] (Names: '|':_UITableViewHeaderFooterContentView:0x7188df0 )>",
"<NSLayoutConstraint:0x7189e30 H:[UILabel:0x71892c0]-(>=10)-[UILabel:0x7189130]>",
"<NSLayoutConstraint:0x718a1f0 H:[UILabel:0x7189130]-(10)-| (Names: '|':_UITableViewHeaderFooterContentView:0x7188df0 )>",
"<NSLayoutConstraint:0x718a3f0 UILabel:0x71892c0.centerY == _UITableViewHeaderFooterContentView:0x7188df0.centerY>",
"<NSLayoutConstraint:0x718a430 UILabel:0x7189130.centerY == _UITableViewHeaderFooterContentView:0x7188df0.centerY>",
"<NSLayoutConstraint:0x718a4b0 UILabel:0x71892c0.height == UILabel:0x7189130.height>"
)
Откуда это ограничение автомасштабирования маски? Куда он идет?
Я что-то упустил? В первый раз, когда я посмотрел на автоматический макет, как неделю назад, так что это вполне возможно.