В iOS-разработке выравнивание контента и интервалы — это то, на что может уйти много времени. Давайте рассмотрим, как устанавливать ограничения с помощью UIKit, обновлять их и разрешать конфликты ограничений.
Ограничение(constraint) - это правило, позволяющее операционной системе размещать ваш компонент пользовательского интерфейса. В UIKit есть 2 основных способа установки ограничений: StoryBoard и кодом. В данной статье рассмотрим только подход кодом.
Создание нового ограничения
Первое, что нам нужно сделать, это отключить AutoresizingMask, который по умолчанию включён.
![](https://habrastorage.org/getpro/habr/upload_files/584/457/275/584457275fd8d86547e623f01c9a59bc.png)
Активация
После создания нам нужно активировать наши ограничения. Для этого вы можете либо переключить ограничение на isActive, по одному, либо использовать.activate() функцию для одновременного обновления пакета ограничений.
![](https://habrastorage.org/getpro/habr/upload_files/b36/eb3/7e4/b36eb37e4d5d12550ecac3015b399a1e.png)
Вы так же можете деактивировать их таким же образом.
![](https://habrastorage.org/getpro/habr/upload_files/6ab/fcc/4aa/6abfcc4aa148c543982d83aaf3b0c056.png)
Управление ограничениями
Ограничения можно обновлять после применения. Например, для изменения интервала или размера
![](https://habrastorage.org/getpro/habr/upload_files/3f5/5b9/985/3f55b99855f40ec16788ed3d8729c4f5.png)
Также можем анимировать view с помощью ограничений. Главное обязательно вызвать layoutIfNeeded()
![](https://habrastorage.org/getpro/habr/upload_files/8d0/50f/edf/8d050fedfd80558951b65c1dae9abbfb.png)
Разрешение конфликтов ограничений
Теперь, когда мы изучили основы добавления, редактирования и активации ограничений, возникает проблема: разрешение конфликтующих ограничений.
В большинстве случаев Xcode укажет в консоли, что не может разрешить ограничения в консоли. При открытии Debug View Hierarchy мы можем проверить каждое ограничение и определить, откуда возникает конфликт.
![](https://habrastorage.org/getpro/habr/upload_files/9b7/7c5/edd/9b77c5edd9502afc7eddb1f7c1c4f72b.png)
Конфликты почти всегда возникают из-за приоритетных вопросов. Если я установлю для ограничения высоты значение, 100
а затем другое ограничение 50
, система не сможет сказать, какое из них применять.
Это создаст конфликт.
![](https://habrastorage.org/getpro/habr/upload_files/113/505/784/113505784890da29974a13ccd685ee2b.png)
Чтобы обнаружить конфликт такого типа, мы можем установить Breakpoint с помощью UIViewAlertForUnsatisfiableConstraints для обнаружения неправильно настроенных ограничений
![](https://habrastorage.org/getpro/habr/upload_files/64a/d2a/da4/64ad2ada47afece964fbeab70c42ef08.png)
Как только мы определили, какие ограничения конфликтуют, мы можем изменить приоритет в пользу одного и уменьшить второе, максимальное значение которого равно 1000
![](https://habrastorage.org/getpro/habr/upload_files/035/8c6/085/0358c6085d1d8d485ade5776e65510a8.png)
Так же есть предопределенные значения, которые мы можем использовать повторно.
![](https://habrastorage.org/getpro/habr/upload_files/933/1a0/494/9331a0494fbd163f5d9f7ab3b587f32a.png)
Intrinsic content size
Вы задавались иногда вопросом почему для Label можно не указывать размер, а для view обязательно? Сейчас мы рассмотрим почему это так происходит
Возьмём и разместим на экране View и Label.
![](https://habrastorage.org/getpro/habr/upload_files/a9f/118/6fc/a9f1186fc4b09bfc9f418e974516cd26.png)
При размещении view xcode выдаст ошибку и не отобразит нашу view
![](https://habrastorage.org/getpro/habr/upload_files/ba6/498/772/ba6498772980ff711993edd927bde51a.png)
При размещении Label на экране спокойно отобразиться наш элемент при размещении Label на экране спокойно отобразиться наш элемент
![](https://habrastorage.org/getpro/habr/upload_files/c75/e17/da4/c75e17da4aaef5b02486f383f90b9994.png)
Intrinsic content size - это размер контента у всех UI элементов (label, view, button и т. д.). Данное свойство определит какого размера должна быть view, чтобы разместить в ней контент. На табличке ниже мы можем рассмотреть Intrinsic content size для разных элементов UI
![](https://habrastorage.org/getpro/habr/upload_files/f28/bc0/56a/f28bc056ab4304c1c84d0202d8edc40b.png)
UIView и NSView - не имеют Intrinsic content size
Sliders - установлена только ширина, нужно задать высоту для слайдера
Labels, buttons, switches, и text fields - определена высота и ширина
Text views image views - Intrinsic content size может изменяться в зависимости от контента внутри (если не добавить контент, то тогда не будут определены размеры)
Auto Layout и Constraint Resistance
Для некоторых UIView мы не всегда можем применить конкретные значения. Например, если у нас есть UIButton с Tap
жестко заданным значением, при локализации текст может быть обрезан.
Чтобы справиться с этим, не требуя изменения приоритета, мы можем использовать другой набор функций, чтобы избежать такого поведения. Двумя из них являются Content Hugging и Content Resistance.
Content hugging priority - приоритет сопротивления превышения intrinsic content size (не хочу чтобы была больше)
Content compression resistance priority - приоритет сопротивления занижения intrinsic content size (не хочу чтобы была меньше)
![](https://habrastorage.org/getpro/habr/upload_files/42c/420/886/42c420886adf5adad1d49cf3481a61d1.png)
Вернемся UIButton. Вместо того чтобы устанавливать ограничение ширины, чтобы избежать обрезки, можно применить сопротивление избежав сжатия. Другой текст локализации расширит его.
![](https://habrastorage.org/getpro/habr/upload_files/9f2/41e/e51/9f241ee5128f0bc50f3e9412add97738.png)
![](https://habrastorage.org/getpro/habr/upload_files/80f/915/3aa/80f9153aaf37ed716e7a58ec6ed83747.png)
Safe area constraints
При поддержке нескольких устройств одной привязки может быть недостаточно. Например, если у вас есть status bar, navigation bar, как мы можем учитываем их размеры на разных устройствах?
К счастью, UIKit поставляется со свойством safeAreaLayoutGuide для адаптации safe area, чтобы мы могли сосредоточиться на view, а не на размеры расстояний между устройствами. Это позволяет нам иметь одинаковый интервал, например, для iPhone8 или iPhone13.
Пример c safeAreaLayoutGuide
![](https://habrastorage.org/getpro/habr/upload_files/d42/703/650/d4270365027c2b8c78278b37c8da343b.png)
Вывод
В заключение, Auto Layout — очень мощный API. Это определенно упростило разработку: применение дизайна на нескольких устройствах и изменение размера до нужного размера.
С ограничением безопасной зоны и различными приоритетами становится проще адаптировать к новым устройствам, от iPhone 13 mini до iPad Pro.
Поскольку мы можем очень быстро создать множество ограничений, может быть трудно отслеживать их все, когда возникает конфликт. К счастью, Xcode поставляется с различными инструментами для отслеживания этого.
Установка ограничений программным путем упрощает поддержку и отладку, поскольку в разработке участвует много человек и работать со storyboard в большой команде будет крайне сложно.