Высота динамических ячеек UITableView корректируется только после некоторой прокрутки

У меня есть UITableView с пользовательским UITableViewCell, определенным в раскадровке с использованием автоматического макета. Ячейка имеет несколько многострочных UILabels.

UITableView, кажется, правильно рассчитывает высоту ячеек, но для первых нескольких ячеек эта высота не разделяется должным образом между метками. После небольшой прокрутки все работает как положено (даже ячейки, которые изначально были неправильными).

- (void)viewDidLoad {
    [super viewDidLoad]
    // ...
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
    // ...
    // Set label.text for variable length string.
    return cell;
}

Есть ли что-то, чего мне может не хватать, из-за чего автоматический макет не может выполнять свою работу первые несколько раз?

Я создал образец проекта, демонстрирующий это поведение.

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


person blackp    schedule 22.09.2014    source источник
comment
Я также столкнулся с этой проблемой, но ответ ниже не работает для меня, любая помощь по этому поводу   -  person Shangari C    schedule 28.06.2016
comment
столкнулся с той же проблемой, добавление layoutIfNeeded для ячейки не работает и у меня? любые другие предложения   -  person Max    schedule 05.09.2016
comment
Отличное место. Это все еще проблема в 2019 году: /   -  person Fattie    schedule 10.10.2019
comment
Я нашел то, что мне помогло, по следующей ссылке - это довольно подробное обсуждение ячеек представления таблицы переменной высоты: stackoverflow.com/a/18746930/ 826946   -  person Andy Weinstein    schedule 22.04.2020


Ответы (27)


Я не знаю, четко это задокументировано или нет, но добавление [cell layoutIfNeeded] перед возвратом ячейки решает вашу проблему.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
    NSUInteger n1 = firstLabelWordCount[indexPath.row];
    NSUInteger n2 = secondLabelWordCount[indexPath.row];
    [cell setNumberOfWordsForFirstLabel:n1 secondLabel:n2];

    [cell layoutIfNeeded]; // <- added

    return cell;
}
person rintaro    schedule 22.09.2014
comment
Я все же задаюсь вопросом, почему это необходимо только в первый раз? Он работает так же хорошо, если я помещаю вызов -layoutIfNeeded в ячейку -awakeFromNib. Я бы предпочел звонить layoutIfNeeded только тогда, когда я знаю, почему это необходимо. - person blackp; 23.09.2014
comment
Сработало у меня! И хотелось бы знать, зачем это нужно! - person Mustafa; 16.01.2015
comment
Не работает, если вы визуализируете класс размера, отличный от любого X any - person Andrei Konstantinov; 08.05.2015
comment
@AndreyKonstantinov Да, он не работает с классом размера, как мне заставить его работать с классом размера? - person z22; 16.11.2015
comment
Он работает без размерного класса, любое решение с размерным классом? - person Yuvrajsinh; 02.08.2016
comment
Это мне помогло (с размерным классом). Сразу после того, как вы запросите и установите текст метки: cell.labelText.preferredMaxLayoutWidth = cell.labelText.frame.width - person 6axter82; 30.01.2017
comment
Не могу поверить, что потратил так много времени, чтобы наконец найти этот рабочий ответ. :) - person Bptstmlgt; 06.11.2017
comment
я хочу подарить тебе этот мир ... :) - person axumnemonic; 28.03.2018
comment
Это мне очень помогло. Спасибо, Ринтаро. - person KSR; 02.12.2020

Это сработало для меня, когда другие подобные решения не работали:

override func didMoveToSuperview() {
    super.didMoveToSuperview()
    layoutIfNeeded()
}

Это похоже на настоящую ошибку, поскольку я хорошо знаком с AutoLayout и тем, как использовать UITableViewAutomaticDimension, однако я все еще иногда сталкиваюсь с этой проблемой. Я рад, что наконец нашел что-то, что работает как обходной путь.

person Michael Peterson    schedule 12.12.2016
comment
Лучше, чем принятый ответ, поскольку он вызывается только тогда, когда ячейка загружается из xib вместо отображения каждой ячейки. Гораздо меньше строк кода. - person Robert Wagstaff; 23.03.2017
comment
Не забудьте позвонить super.didMoveToSuperview() - person cicerocamargo; 28.09.2017
comment
@cicerocamargo Apple говорит о didMoveToSuperview: Реализация этого метода по умолчанию ничего не делает. - person Ivan Smetanin; 17.10.2018
comment
@IvanSmetanin не имеет значения, если реализация по умолчанию ничего не делает, вы все равно должны вызывать супер-метод, так как он действительно может что-то сделать в будущем. - person TNguyen; 07.03.2019
comment
(Просто между прочим, вы должны ОБЯЗАТЕЛЬНО назвать super. По этому поводу. Я никогда не видел проекта, в котором команда в целом не делала бы подклассы более одного раза ячеек, поэтому, конечно, вы должны быть уверены, что выбрали их все. И как отдельный вопрос, что сказал TNguyen.) - person Fattie; 10.10.2019
comment
Это должно быть в TableView или в ячейке? - person Julian Wagner; 27.10.2019
comment
Это ТОЛЬКО помогло мне отлично работать. Все вышеперечисленное ничего для меня не сделало (используя ячейку tableview в другой ячейке tableview, Swift 4.0). - person KoreanXcodeWorker; 18.05.2020

Добавление [cell layoutIfNeeded] в cellForRowAtIndexPath не работает для ячеек, которые изначально прокручиваются вне поля зрения.

И не ставит перед ним [cell setNeedsLayout].

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

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

person Scenario    schedule 12.05.2015
comment
Мне то же. когда я впервые прокручиваю, размер ячейки составляет 44 пикселя. если я прокручиваю, чтобы убрать ячейку из поля зрения и вернуться обратно, размер ее будет правильным. Вы нашли какое-нибудь решение? - person Max; 18.06.2015
comment
Спасибо @ ashy_32bit, это тоже решило эту проблему для меня. - person ImpurestClub; 18.08.2015
comment
это может показаться простой ошибкой, @Scenario не так ли? ужасные вещи. - person Fattie; 24.09.2015
comment
Использование [cell layoutSubviews] вместо layoutIfNeeded могло бы стать возможным исправлением. Обратитесь к stackoverflow.com/a/33515872/1474113 - person ypresto; 13.11.2015

У меня был такой же опыт в одном из моих проектов.

Почему так происходит?

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

Вот проблема:

tableView:heightForRowAtIndexPath: вызывается перед макетом ячейки, это подпредставления.

Таким образом, он рассчитал высоту для метки и ячейки шириной 400 пикселей. Но вы работаете на устройстве с экраном, например, 320 пикселей. И эта автоматически рассчитанная высота неверна. Просто потому, что layoutSubviews ячейки происходит только после tableView:heightForRowAtIndexPath:. Даже если вы вручную установите preferredMaxLayoutWidth для своей метки в layoutSubviews, это не поможет.

Мое решение:

1) Подкласс UITableView и переопределить dequeueReusableCellWithIdentifier:forIndexPath:. Установите ширину ячейки равной ширине таблицы и задайте макет ячейки.

- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [super dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    CGRect cellFrame = cell.frame;
    cellFrame.size.width = self.frame.size.width;
    cell.frame = cellFrame;
    [cell layoutIfNeeded];
    return cell;
}

2) Подкласс UITableViewCell. Установите preferredMaxLayoutWidth вручную для ваших этикеток в layoutSubviews. Также вам нужно вручную разметить contentView, потому что он не компоновка автоматически после изменения рамки ячейки (я не знаю почему, но это так)

- (void)layoutSubviews {
    [super layoutSubviews];
    [self.contentView layoutIfNeeded];
    self.yourLongTextLabel.preferredMaxLayoutWidth = self.yourLongTextLabel.width;
}
person Vitalii Gozhenko    schedule 28.09.2015
comment
Когда я столкнулся с этой проблемой, мне также нужно было убедиться, что фрейм табличного представления был правильным, поэтому я вызвал [self.tableview layoutIfNeeded] перед заполнением табличного представления (в viewDidLoad). - person GK100; 30.05.2016
comment
Я никогда не переставал думать, что это связано с неправильной шириной. cell.frame.size.width = tableview.frame.width затем cell.layoutIfNeeded() в cellForRowAt функции помогли мне - person Cam Connor; 10.07.2020

У меня аналогичная проблема, при первой загрузке высота строки не рассчитывалась, но после некоторой прокрутки или перехода на другой экран, и я возвращаюсь к этому экрану, строки вычисляются. При первой загрузке мои элементы загружаются из Интернета, а при второй загрузке мои элементы загружаются сначала из Core Data и перезагружаются из Интернета, и я заметил, что высота строк рассчитывается при перезагрузке из Интернета. Итак, я заметил, что когда tableView.reloadData () вызывается во время анимации перехода (такая же проблема с push и текущим переходом), высота строки не вычислялась. Поэтому я спрятал tableview при инициализации представления и поставил загрузчик активности, чтобы предотвратить неприятный эффект для пользователя, и я вызываю tableView.reloadData через 300 мс, и теперь проблема решена. Я думаю, что это ошибка UIKit, но этот обходной путь поможет.

Я помещаю эти строки (Swift 3.0) в свой обработчик завершения загрузки элемента

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute: {
        self.tableView.isHidden = false
        self.loader.stopAnimating()
        self.tableView.reloadData()
    })

Это объясняет, почему некоторые люди помещают reloadData в layoutSubviews, чтобы решить проблему.

person alvinmeimoun    schedule 26.12.2016
comment
Это единственный WA, который у меня тоже сработал. За исключением того, что я не использую isHidden, но устанавливаю альфа таблицы на 0 при добавлении источника данных, а затем на 1 после перезагрузки. - person PJ_Finnegan; 13.11.2017

Ни одно из вышеперечисленных решений у меня не сработало, сработал этот рецепт волшебства: назовите их в таком порядке:

tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()

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

person JAHelia    schedule 03.04.2019
comment
Для Swift 5 это сработало даже в режиме коллекции, да благословит вас Бог, братан. - person Govani Dhruv Vijaykumar; 06.05.2020
comment
Для меня это вернуло правильную высоту и расположение ячейки, но в нем не было данных. - person Darrow Hartman; 12.05.2020
comment
Попробуйте setNeedsDisplay () после этих строк - person JAHelia; 12.05.2020

Я попробовал ответить на большинство ответов на этот вопрос и не смог заставить работать ни один из них. Единственное функциональное решение, которое я нашел, - это добавить к моему подклассу UITableViewController следующее:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    UIView.performWithoutAnimation {
        tableView.beginUpdates()
        tableView.endUpdates()
    }
}

Требуется вызов UIView.performWithoutAnimation, в противном случае вы увидите обычную анимацию табличного представления при загрузке контроллера представления.

person Chris Vig    schedule 30.05.2017
comment
работает и определенно лучше, чем дважды вызывать reloadData - person Jimmy George Thomas; 19.07.2017
comment
Черная магия. Выполнение этого в viewWillAppear не помогло мне, но выполнение этого в viewDidAppear сработало. - person Martin; 11.10.2017
comment
Это решение сработало для меня, когда оно было реализовано в viewDidAppear. Это ни в коем случае не оптимально для взаимодействия с пользователем, поскольку содержимое таблицы перескакивает по мере того, как происходит правильный размер. - person richardpiazza; 28.11.2017
comment
потрясающе, я пробовал много примеров, но потерпел неудачу, ты демон - person Shakeel Ahmed; 13.11.2019
comment
То же, что и @martin - person A.J. Hernandez; 22.03.2020

В моем случае последняя строка UILabel была усечена при первом отображении ячейки. Это произошло довольно случайно, и единственный способ правильно определить размер - это прокрутить ячейку из поля зрения и вернуть ее обратно. Я пробовал все возможные решения, представленные до сих пор (layoutIfNeeded..reloadData), но у меня ничего не сработало. Хитрость заключалась в том, чтобы установить для Автоусадки значение Минимальный масштаб шрифта (0,5 для меня). Попробуйте

person Claus    schedule 01.05.2015
comment
это сработало для меня, без применения каких-либо других решений, перечисленных выше. Отличная находка. - person mckeejm; 09.09.2015
comment
Но это автоматически уменьшает текст ... зачем нужно иметь разные размеры текста в табличном представлении? Выглядит ужасно. - person lucius degeer; 29.09.2017

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

    override func viewDidLoad() {
    super.viewDidLoad()

    tableView.estimatedRowHeight = 70
    tableView.rowHeight = UITableViewAutomaticDimension
}

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

class CustomTableViewCell: UITableViewCell {

override func awakeFromNib() {
    super.awakeFromNib()
    self.layoutIfNeeded()
    // Initialization code
}
}
person bikram sapkota    schedule 08.08.2016
comment
Важно установить estimatedRowHeight на значение ›0, а не на UITableViewAutomaticDimension (то есть -1), иначе автоматическая высота строки не будет работать. - person PJ_Finnegan; 13.11.2017

В моем случае помогает установка preferredMaxLayoutWidth. я добавил

cell.detailLabel.preferredMaxLayoutWidth = cell.frame.width

в моем коде.

Также см. Однострочный текст занимает две строки в UILabel и http://openradar.appspot.com/17799811.

person Xhacker Liu    schedule 09.06.2015

вызов cell.layoutIfNeeded() внутри cellForRowAt работал у меня на ios 10 и ios 11, но не на ios 9.

чтобы получить эту работу и на ios 9, я позвонил cell.layoutSubviews(), и это помогло.

person axumnemonic    schedule 28.03.2018

Прикрепление снимка экрана для вашей справки Для меня ни один из этих подходов не работал, но я обнаружил, что метка явно Preferred Width установлена ​​в Interface Builder. Удаление этого (снятие флажка "Явный") и последующее использование UITableViewAutomaticDimension сработало, как ожидалось.

person Jack James    schedule 24.02.2017

Я попробовал все решения на этой странице, но снятие флажка с использованием классов размеров, а затем повторная проверка решило мою проблему.

Изменить: снятие отметки с классов размеров вызывает много проблем на раскадровке, поэтому я попробовал другое решение. Я заполнил представление таблицы в методах viewDidLoad и viewWillAppear контроллера представления. Это решило мою проблему.

person ACengiz    schedule 25.09.2015

У меня проблема с изменением размера метки, поэтому мне нужно просто сделать
chatTextLabel.text = chatMessage.message chatTextLabel? .UpdateConstraints () после настройки текста

// полный код

func setContent() {
    chatTextLabel.text = chatMessage.message
    chatTextLabel?.updateConstraints()

    let labelTextWidth = (chatTextLabel?.intrinsicContentSize().width) ?? 0
    let labelTextHeight = chatTextLabel?.intrinsicContentSize().height

    guard labelTextWidth < originWidth && labelTextHeight <= singleLineRowheight else {
      trailingConstraint?.constant = trailingConstant
      return
    }
    trailingConstraint?.constant = trailingConstant + (originWidth - labelTextWidth)

  }
person Svitlana    schedule 20.05.2016

В моем случае я обновлялся в другом цикле. Таким образом, высота tableViewCell была обновлена ​​после установки labelText. Я удалил асинхронный блок.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier:Identifier, for: indexPath) 
     // Check your cycle if update cycle is same or not
     // DispatchQueue.main.async {
        cell.label.text = nil
     // }
}
person Den Jo    schedule 04.04.2017
comment
У меня тоже есть асинхронный блок, но он нужен? Альтернативы нет? - person Nazar Medeiros; 20.07.2020

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

Пришлось добавить следующее в viewDidLoad ().

DispatchQueue.main.async {

        self.tableView.reloadData()

        self.tableView.setNeedsLayout()
        self.tableView.layoutIfNeeded()

        self.tableView.reloadData()

    }

Вышеупомянутая комбинация reloadData, setNeedsLayout и layoutIfNeeded работала, но не другие. Однако может быть специфическим для ячеек в проекте. И да, пришлось дважды вызывать reloadData, чтобы он заработал.

Также установите следующее в viewDidLoad

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = MyEstimatedHeight

В tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)

cell.setNeedsLayout()
cell.layoutIfNeeded() 
person Jimmy George Thomas    schedule 22.04.2017
comment
Мой аналог reloadData/beginUpdates/endUpdates/reloadData тоже работает; reloadData необходимо вызвать во второй раз. Не нужно оборачивать async. - person ray; 25.07.2018

Просто убедитесь, что вы не устанавливаете текст метки в методе делегата willdisplaycell представления таблицы. Задайте текст метки в методе делегата cellForRowAtindexPath для динамического расчета высоты.

Пожалуйста :)

person Pranav Rivankar    schedule 25.05.2017

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

person Guilherme Carvalho    schedule 26.05.2017
comment
Я пробовал все другие решения, только ваше решение сработало, спасибо, что поделились им - person tamtoum1987; 07.12.2019

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

- (void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];
  [self.tableView reloadData];
}
person alicanozkara    schedule 20.11.2017
comment
это было намного лучше, чем лучшее решение, которое помогло мне. Он не исправлял 100% ячейки, но до 80% принимали их фактический размер. Большое спасибо - person TheTravloper; 11.01.2019

Только для iOS 12+, начиная с 2019 г. ...

Постоянный пример случайной странной некомпетентности Apple, когда проблемы длятся буквально годами.

Похоже, что

        cell.layoutIfNeeded()
        return cell

исправлю это. (Вы, конечно, теряете производительность.)

Такова жизнь с Apple.

person Fattie    schedule 10.10.2019

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

[self.tableView reloadData];

Я действительно пробовал

[cell layoutIfNeeded];

но это не сработало.

person Chris Prince    schedule 04.11.2016

В Swift 3. Мне приходилось вызывать self.layoutIfNeeded () каждый раз, когда я обновляю текст повторно используемой ячейки.

import UIKit
import SnapKit

class CommentTableViewCell: UITableViewCell {

    static let reuseIdentifier = "CommentTableViewCell"

    var comment: Comment! {
        didSet {
            textLbl.attributedText = comment.attributedTextToDisplay()
            self.layoutIfNeeded() //This is a fix to make propper automatic dimentions (height).
        }
    }

    internal var textLbl = UILabel()

    override func layoutSubviews() {
        super.layoutSubviews()

        if textLbl.superview == nil {
            textLbl.numberOfLines = 0
            textLbl.lineBreakMode = .byWordWrapping
            self.contentView.addSubview(textLbl)
            textLbl.snp.makeConstraints({ (make) in
                make.left.equalTo(contentView.snp.left).inset(10)
                make.right.equalTo(contentView.snp.right).inset(10)
                make.top.equalTo(contentView.snp.top).inset(10)
                make.bottom.equalTo(contentView.snp.bottom).inset(10)
            })
        }
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let comment = comments[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: CommentTableViewCell.reuseIdentifier, for: indexPath) as! CommentTableViewCell
        cell.selectionStyle = .none
        cell.comment = comment
        return cell
    }

commentsTableView.rowHeight = UITableViewAutomaticDimension
    commentsTableView.estimatedRowHeight = 140
person Naloiko Eugene    schedule 13.01.2017

Я столкнулся с этой проблемой и исправил ее, переместив код инициализации представления / метки С tableView(willDisplay cell:) НА tableView(cellForRowAt:).

person raisedandglazed    schedule 12.06.2017
comment
что НЕ рекомендуется для инициализации ячейки. willDisplay будет иметь лучшую производительность, чем cellForRowAt. Используйте самую последнюю только для создания экземпляра нужной ячейки. - person Martin; 11.10.2017
comment
Спустя 2 года я читаю тот старый комментарий, который написал. Это был плохой совет. Даже если willDisplay имеют лучшую производительность, рекомендуется инициализировать пользовательский интерфейс ячейки в cellForRowAt, когда макет является автоматическим. Действительно, макет вычисляется UIKit после cellForRowAt и до willDisplay. Поэтому, если высота вашей ячейки зависит от ее содержимого, инициализируйте содержимое метки (или что-то еще) в cellForRowAt. - person Martin; 23.03.2020

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

tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
let cell = tableView.cellForRow(at: indexPath) ?? UITableViewCell()
let size = cell.systemLayoutSizeFitting(CGSize(width: frame.size.width, height: UIView.layoutFittingCompressedSize.height))
person hundreth    schedule 22.01.2021

iOS 11+

в табличных представлениях по умолчанию используется расчетная высота. Это означает, что contentSize изначально соответствует расчетному значению. Если вам нужно использовать contentSize, вы захотите отключить оценку высоты, установив для трех свойств оценки высоты ноль: tableView.estimatedRowHeight = 0 tableView.estimatedSectionHeaderHeight = 0 tableView.estimatedSectionFooterHeight = 0

    public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
        return CGFloat.leastNormalMagnitude
    }

    public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return CGFloat.leastNormalMagnitude
    }

    public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
        return CGFloat.leastNormalMagnitude
    }
person Binoy jose    schedule 03.03.2021

Другое решение

@IBOutlet private weak var tableView: UITableView! {
    didSet {
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = UITableView.automaticDimension
    }
}

extension YourViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        UITableView.automaticDimension
    }
}

Тогда макет не нужен.

person Oleksii    schedule 08.04.2021

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{


//  call the method dynamiclabelHeightForText
}

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

-(int)dynamiclabelHeightForText:(NSString *)text :(int)width :(UIFont *)font
{

    CGSize maximumLabelSize = CGSizeMake(width,2500);

    CGSize expectedLabelSize = [text sizeWithFont:font
                                constrainedToSize:maximumLabelSize
                                    lineBreakMode:NSLineBreakByWordWrapping];


    return expectedLabelSize.height;


}

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

person Ramesh Muthe    schedule 22.09.2014
comment
На самом деле, Рамеш, в этом нет необходимости, если установлены свойства tableView.estimatedRowHeight и tableView.rowHeight = UITableViewAutomaticDimension. Кроме того, убедитесь, что настраиваемая ячейка имеет соответствующие ограничения для различных виджетов и contentView. - person BonanzaDriver; 16.01.2015