В чем разница между setNeedsLayout, layoutSubviews и updateConstraints в iOS
Что проверяют
Понимаете ли вы, что разметка идёт отложенным проходом, и не вызываете ли её вручную. Это тема, где неверные привычки дают то тормоза, то бесконечные циклы.
Как отвечать
Разложите по ролям в цикле разметки:
setNeedsLayout()помечает представление как требующее пересчёта. Возвращается сразу, сам пересчёт произойдёт в ближайшем проходе разметки. Это то, что вызывают из своего кода;layoutSubviews()это сам пересчёт: система вызывает его, когда пришло время расставить подвиды. Его переопределяют, но никогда не вызывают напрямую;layoutIfNeeded()заставляет пересчёт произойти прямо сейчас, синхронно. Нужен редко: например, чтобы анимировать изменение ограничений или получить актуальные размеры до конца кадра;setNeedsUpdateConstraints()иupdateConstraints()это та же пара, но уровнем выше: не расстановка кадров, а пересчёт самих ограничений. ПереопределятьupdateConstraintsстоит только когда ограничения меняются часто и их пересчёт заметно дорог. В обычном коде ограничения меняют напрямую, и этого достаточно.
Порядок такой: пометили пересчёт → система обновляет ограничения → выполняет разметку (layoutSubviews сверху вниз по иерархии) → рисует.
Обязательные правила: в layoutSubviews вызывают super, не создают объекты и не добавляют ограничения (метод вызывается многократно), не вызывают setNeedsLayout на себе изнутри, иначе получается бесконечный цикл.
Где спотыкаются
Вызывают layoutSubviews() руками вместо setNeedsLayout().
Ставят layoutIfNeeded() в каждый метод «на всякий случай» и получают лишние синхронные проходы в прокрутке.
Добавляют ограничения внутри updateConstraints без проверки, и они накапливаются при каждом вызове.