Автомакет + ограничения для динамической высоты таблицы на основе общего количества строк

В первую очередь речь идет не о динамической высоте ячейки. Так что не путайте это.

У меня есть сценарий, в котором я создал три карты

  1. Карточка сведений: Показать конкретные сведения о местоположении
  2. Карточка диаграммы: отображение различных диаграмм в зависимости от выбора
  3. Карточка с дополнительными сведениями: на карточке показаны дополнительные сведения

Ниже приведены скрины для вышеуказанных карт:

введите здесь описание изображения введите здесь описание изображения введите здесь описание изображения

Просмотр иерархии для указанных выше экранов:

  • Controller
    • ScrollView
    • Карта-1
    • Карта-2
    • Card-3 <---- We are interested in this card
      • Custom View
        • TableView

Итак, я показываю ограничения для последней карты здесь, все вышеперечисленные карты работают идеально! и нет ограничений двусмысленности или предупреждений.

Пройдемся по коду:

Сначала добавьте Card-3 к ScrollView: здесь chartBox — это карточка-2, а bottomBox — карточка-3.

[self.scrollView addConstraints:[NSLayoutConstraint
                                 constraintsWithVisualFormat:@"V:[chartBox(200)]-(10)-[bottomBox]"
                                 options:0
                                 metrics:nil
                                 views:@{@"bottomBox" : self.bottomBox, @"chartBox" : self.chartBox}]];

// Below constraint pin to increase content-size
[self.scrollView addConstraints:[NSLayoutConstraint
                                constraintsWithVisualFormat:@"V:[bottomBox]-(10)-|"
                                options:0
                                metrics:nil
                                views:@{@"bottomBox" : self.bottomBox}]];

[self.scrollView addConstraints:[NSLayoutConstraint
                                constraintsWithVisualFormat:@"H:[bottomBox]-(10)-|"
                                options:0
                                metrics:nil
                                views:@{@"bottomBox" : self.bottomBox}]];

Второе добавление CustomView к Card-3: здесь bluePrintView — это CustomView.

_bluePrintView = [[BluePrintView alloc] init];
self.bluePrintView.translatesAutoresizingMaskIntoConstraints = NO;
[self.bottomBox addSubview:self.bluePrintView];

[self.bottomBox addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bluePrintView]|" options:0 metrics:nil views:@{@"bluePrintView":self.bluePrintView}]];
[self.bottomBox addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[bluePrintView]|" options:0 metrics:nil views:@{@"bluePrintView":self.bluePrintView}]];

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width - 20;
NSDictionary *metrices = @{@"width" : [NSNumber numberWithFloat:screenWidth]};
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[bottomBox(width)]" options:0 metrics:metrices views:@{ @"bottomBox": self.bottomBox}]];

Третье добавление TableView к CustomView:

self.tableView.tableFooterView = [[UIView alloc] init];

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:@{@"tableView":self.tableView}]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[tableView]|" options:0 metrics:nil views:@{@"tableView":self.tableView}]];

// Height constraint
CGFloat viewHeight = self.bounds.size.height;
self.tableHeightConstraint = [NSLayoutConstraint constraintWithItem:self.tableView
                                                          attribute:NSLayoutAttributeHeight
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:nil
                                                          attribute:NSLayoutAttributeNotAnAttribute
                                                         multiplier:1.0
                                                           constant:viewHeight];
[self addConstraint:self.tableHeightConstraint];

[self.tableView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];

И в методе наблюдателя я обновлю ограничение tableHeightConstraint.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    self.tableHeightConstraint.constant = self.tableView.contentSize.height;
    [self.tableView setNeedsLayout];
    [self.tableView layoutIfNeeded];
}

После попытки все возможности заканчиваются здесь. Предупреждения об ограничениях.

(
    "<NSLayoutConstraint:0x7fbeb1e7e8e0 V:|-(0)-[UITableView:0x7fbeb2843000]   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>",
    "<NSLayoutConstraint:0x7fbeb1e7e700 V:[UITableView:0x7fbeb2843000]-(0)-|   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>",
    "<NSLayoutConstraint:0x7fbeb1e7e9b0 V:[UITableView:0x7fbeb2843000(480)]>",
    "<NSLayoutConstraint:0x7fbeb1e81a20 '_UITemporaryLayoutHeight' V:[BluePrintView:0x7fbeb1e7ac30(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fbeb1e7e700 V:[UITableView:0x7fbeb2843000]-(0)-|   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>

Я решил эти предупреждения, удалив строку | из [tableView] (путем удаления нижнего ограничения для superView), но тогда tableView не получает желаемую высоту.

Любая идея, как получить полную высоту tableView без каких-либо предупреждений об ограничениях.

P.S. Все представления создаются с помощью кода, без XIB и макета раскадровки. iOS 9.2


person Kampai    schedule 12.02.2016    source источник


Ответы (1)


Я не видел ошибок в настройке ваших ограничений.

Вы можете увидеть это ограничение UITemporaryLayoutHeight, потому что вы добавили наблюдатель contentSize ([self.tableView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL]) слишком рано в жизненном цикле вашего представления, что вызывает ошибку [self.tableView layoutIfNeeded].

Попробуйте добавить наблюдателя в viewDidLoad, удалите его в dealloc вашего контроллера представления; Или в вашем viewWillAppear, и удалить его в viewWillDisappear например.

person Tanguy G.    schedule 12.02.2016
comment
Да ты прав. Этот наблюдатель скоро будет добавлен в жизненный цикл. Я пришел с решением, которое добавляет таймер и задержку на 0,5 секунды для вызова после того, как метод жизненного цикла представления завершит его выполнение. И это работает. - person Kampai; 15.02.2016