Подтвердить что ты не робот

Что такое NSLayoutConstraint "UIView-Encapsulated-Layout-Height" и как мне заставить заставить его пересчитать чистоту?

У меня есть UITableView, работающий под iOS 8, и я использую автоматическую высоту ячеек из ограничений в раскадровке.

Одна из моих ячеек содержит один UITextView, и мне нужно, чтобы он сокращался и расширялся на основе пользовательского ввода - нажмите, чтобы уменьшить/развернуть текст.

Я делаю это, добавляя ограничение времени выполнения в текстовое представление и изменяя константу в ограничении в ответ на пользовательские события:

-(void)collapse:(BOOL)collapse; {

    _collapsed = collapse;

    if(collapse)
            [_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
        else
            [_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];

    [self setNeedsUpdateConstraints];

}

Когда я это сделаю, я переношу его в обновления tableView и вызываю [tableView setNeedsUpdateConstraints]:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView setNeedsUpdateConstraints];
// I have also tried 
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.

[tableView endUpdates];

Когда я это делаю, моя ячейка расширяется (и анимируется при ее выполнении), но я получаю предупреждение о ограничениях:

2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 

(

    "<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",

    "<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-|   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"



 )

Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>

388 - моя расчетная высота, другие ограничения на UITextView являются моими из Xcode/IB.

Последний беспокоит меня - я предполагаю, что UIView-Encapsulated-Layout-Height - это вычисленная высота ячейки при ее первом рендеринге (я установил, что мой размер UITextView должен быть >= 70,0), однако он не кажется правильным, что это производное ограничение затем перекрывает обновленный пользовательский cnstraint.

Хуже того, хотя код макета говорит, что он пытается сломать ограничение по высоте, он этого не делает - он продолжает пересчитывать высоту ячейки, и все рисует, как хотелось бы.

Итак, что такое NSLayoutConstraint UIView-Encapsulated-Layout-Height (я предполагаю, что это расчетная высота для автоматического выбора размеров ячеек) и как мне заставить заставить его пересчитать чисто?

4b9b3361

Ответ 1

Попытайтесь снизить приоритет вашего _collapsedtextHeightConstraint до 999. Таким образом, система, снабженная ограничением UIView-Encapsulated-Layout-Height, всегда имеет приоритет.

Он основан на том, что вы возвращаете в -tableView:heightForRowAtIndexPath:. Обязательно верните правильное значение и ваше собственное ограничение, а сгенерированное должно быть одинаковым. Более низкий приоритет для вашего собственного ограничения требуется только временно, чтобы предотвратить конфликты, когда анимация сжимания/разворота находится в полете.

Ответ 2

У меня есть аналогичный сценарий: представление таблицы с одной ячейкой строки, в которой есть несколько строк объектов UILabel. Я использую iOS 8 и автозапуск.

Когда я повернул, я получил неверную подсчитанную высоту строки (43.5 намного меньше фактической высоты). Это выглядит так:

"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"

Это не просто предупреждение. Макет моей таблицы просмотра таблицы ужасен - весь текст накладывается на одну текстовую строку.

Меня удивляет, что следующая строка "исправляет" мою проблему магически (автоопределение ничего не жалуется, и я получаю то, что ожидаю на экране):

myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works

с или без этой строки:

myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem

Ответ 3

Я смог получить предупреждение, чтобы уйти, указав приоритет на одно из значений в ограничении, которое предупреждающие сообщения говорят, что он должен был сломаться (ниже "Will attempt to recover by breaking constraint"). Похоже, что, пока я устанавливаю приоритет на нечто большее, чем 49, предупреждение исчезает.

Для меня это означало изменение моего ограничения, предупреждающее, что оно попыталось сломаться:

@"V:|[contentLabel]-[quoteeLabel]|"

в

@"V:|[email protected][contentLabel]-[quoteeLabel]|"

Фактически, я могу добавить приоритет к любому из элементов этого ограничения, и он будет работать. Кажется, не имеет значения, какой из них. Мои ячейки достигают правильной высоты, и предупреждение не отображается. Роджер, для вашего примера, попробуйте добавить @500 сразу после ограничения значения высоты 388 (например, [email protected]).

Я не совсем уверен, почему это работает, но я немного разобрался. В перечислении NSLayoutPriority показано, что уровень приоритета NSLayoutPriorityFittingSizeCompression равен 50. Документация для этого уровня приоритета говорит:

Когда вы отправляете сообщение fitSize в представление, наименьший размер, который достаточно велика для вычисления содержимого представления. Это уровень приоритета, с которым представление хочет быть как можно меньше в это вычисление. Это довольно низко. Как правило, это не подходит для сделать ограничение именно с этим приоритетом. Вы хотите быть выше или ниже.

documentation для ссылочного сообщения fittingSize:

Минимальный размер представления, который удовлетворяет ограничениям, которые он имеет. (Только для чтения)

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

Я не вырыл за пределами этого, но кажется, что имеет смысл, что это имеет какое-то отношение к тому, где проблема.

Ответ 4

Вместо того, чтобы информировать представление таблицы об обновлении своих ограничений, попробуйте перезагрузить ячейку:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];

[tableView endUpdates];

UIView-Encapsulated-Layout-Height - это, вероятно, высота представления таблицы для ячейки во время начальной загрузки на основе ограничений ячейки в это время.

Ответ 5

Другая возможность:

Если вы используете автоматическую компоновку для вычисления высоты ячейки (высота содержимого, большую часть времени, как показано ниже), и если у вас есть разделитель uitableview, вам нужно добавить высоту разделителя, чтобы вернуться к высоте ячейки. Как только вы получите правильную высоту, у вас не будет этого предупреждения автоопределения.

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
   [sizingCell setNeedsLayout];
   [sizingCell layoutIfNeeded];
   CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
   return size.height; // should + 1 here if my uitableviewseparatorstyle is not none

}

Ответ 6

Определение размера текстового представления в соответствии с его содержимым и обновление константы ограничения высоты до конечной высоты, исправление конфликта ограничений UIView-Encapsulated-Layout-Height для меня, например:

[self.textView sizeToFit];
self.textViewHeightConstraint.constant = self.textView.frame.size.height;

Ответ 7

После нескольких часов, царапающих мою голову этой ошибкой, я наконец нашел решение, которое сработало для меня. моя основная проблема заключалась в том, что у меня было несколько писем, зарегистрированных для разных типов ячеек, но одному типу ячеек было разрешено иметь разные размеры (не все экземпляры этой ячейки будут одинакового размера). поэтому проблема возникла, когда tableview пытался удалить из ячейки ячейки такого типа, и она имела разную высоту. Я решил это, установив

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

что-то вроде

cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

Надеюсь, это поможет!

Ответ 8

TableView получает высоту для ячейки в indexPath из делегата. затем введите ячейку из cellForRowAtIndexPath:

top ([email protected])
    cell
bottom ([email protected])

if cell.contentView.height: 0// ↔ (UIView-Encapsulated-Layout-Height: 0 @1000)      top (10 @1000) противоречит (UIView-Encapsulated-Layout-Height: 0 @1000),

из-за их приоритетов равно 1000. Нам нужно установить приоритет в приоритете UIView-Encapsulated-Layout-Height.

Ответ 9

Я получал сообщение вроде этого:

Невозможно одновременно удовлетворить ограничения...
...
...
...
NSLayoutConstraint: 0x7fe74bdf7e50 'UIView-Encapsulated-Layout-Height' В: [UITableViewCellContentView: 0x7fe75330c5c0 (21.5)]
...
...
Попытаться восстановить, нарушив ограничение NSLayoutConstraint: 0x7fe0f9b200c0 UITableViewCellContentView: 0x7fe0f9b1e090.bottomMargin == UILabel: 0x7fe0f9b1e970.bottom

Я использую пользовательский UITableViewCell с UITableViewAutomaticDimension для высоты. И я также реализовал метод estimatedHeightForRowAtIndex:.

Ограничение, которое давало мне проблемы, выглядело примерно так.

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[title]-|" options:0 metrics:nil views:views];

Изменение ограничения на это устранит проблему, но, как и другой ответ, я почувствовал, что это неверно, поскольку оно снижает приоритет ограничения, которое я хочу требовать:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[email protected][title][email protected]|" options:0 metrics:nil views:views];

Однако я заметил, что если я просто удалю приоритет, это также работает, и я не получаю журналы ломающихся ограничений:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[title]-6-|" options:0 metrics:nil views:views];

Это немного тайна относительно того, какая разница между |-6-[title]-6-| и |-[title-|. Но указание размера не является проблемой для меня, и оно избавляется от журналов, и мне не нужно понижать приоритет моих необходимых ограничений.

Ответ 10

Как упоминалось в Jesse в вопросительном комментарии, это работает для меня:

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

FYI, эта проблема не возникает в iOS 10.

Ответ 11

Установите этот view.translatesAutoresizingMaskIntoConstraints = NO;, чтобы решить эту проблему.