Разработка
Наконец-то я нашел применение для .fixedSize
Я годами избегал этого модификатора, потому что само название звучало как ловушка. Затем возникла проблема с компоновкой, которую мог решить только он.
Если бы неделю назад мне сказали, что .fixedSize спасёт мне вторую половину рабочего дня, я бы рассмеялся.
Уже одно название словно предупреждает: этот модификатор загонит вас в угол. Кому вообще нужны представления, зафиксированные в статическом размере? Поэтому, как и многие разработчики на SwiftUI, я мысленно отправил его в категорию «модификаторы, которыми я никогда не воспользуюсь».
А затем мне досталась задача по компоновке, которую — вот неожиданность — можно было аккуратно решить только с помощью .fixedSize.
И она преподала мне урок, который стоило усвоить много лет назад: плохих API не существует — бывают лишь интерфейсы, для которых вы ещё не нашли подходящий сценарий. Каждый модификатор SwiftUI появился по определённой причине. Принципиально избегая какого-то из них, вы без всякой пользы сокращаете собственный набор инструментов.
Давайте разберём задачу.
Задача
Требование звучало просто:
Мы хотим, чтобы все элементы в области прокрутки имели такую же высоту, как самый высокий из них.
Представьте горизонтальный ScrollView, внутри которого находится HStack. Каждый элемент представляет собой карточку с заголовком и описанием.
Длина описаний различается: некоторые короткие, другие длинные. Команда дизайнеров не хотела обрезать текст. Нужно было лишь сделать так, чтобы высота всех карточек соответствовала самой высокой карточке. Тогда строка выглядела бы аккуратно и продуманно, а не состояла из элементов разной высоты.
Цель: растянуть короткую карточку до высоты самой высокой независимо от того, какой именно элемент оказался самым высоким.
Звучит элементарно, правда? На самом деле нет — особенно когда вы годами избегали единственного модификатора, способного решить задачу.
Первая попытка и почему она дала обратный результат
Первой мыслью было очевидное решение: заставить каждую карточку заполнить всё доступное пространство по вертикали.
ScrollView(.horizontal) {
HStack(alignment: .top, spacing: 16) {
ForEach(items) { item in
CardView(item: item)
.frame(maxHeight: .infinity, alignment: .topLeading)
}
}
}
Результат?

Все карточки растянулись на всю высоту экрана. В каком-то смысле задача была выполнена.
Вот почему это произошло: у HStack не было собственного ограничения по высоте, поэтому он принял предложенный родительским ScrollView размер — фактически высоту всего экрана. После этого .frame(maxHeight: .infinity) на каждой карточке с готовностью растянул её до размеров огромного контейнера.
Получилась половина решения. Высота карточек действительно стала одинаковой. Оставалось только заставить сам HStack перестать занимать всё доступное пространство и уменьшиться до высоты самой высокой карточки.
Модификатор, которого я избегал
Именно это делает .fixedSize(horizontal: false, vertical: true). Он сообщает представлению:
Игнорируй высоту, предложенную родителем, и определи собственную высоту на основании идеального размера содержимого.
ScrollView(.horizontal) {
HStack(alignment: .top, spacing: 16) {
ForEach(items) { item in
CardView(item: item)
.frame(maxHeight: .infinity, alignment: .topLeading)
}
}
.fixedSize(horizontal: false, vertical: true) // 👈 the one line that fixes everything
}
В результате все карточки получают высоту самого высокого элемента, а сама строка не становится выше, чем необходимо.

Почему это действительно работает 🤔
Стоит подробнее рассмотреть происходящее при компоновке. Это отличный пример того, как в SwiftUI работает модель «родитель предлагает размер, ребёнок принимает решение».
ScrollViewпредлагаетHStackвсю доступную высоту..fixedSize(vertical: true)перехватывает это предложение: «Спасибо, но я выберу идеальную высоту на основании содержимого».- Идеальная высота
HStackравна высоте самого высокого дочернего элемента. HStackпредлагает эту зафиксированную высоту каждой карточке..frame(maxHeight: .infinity)растягивает все карточки до этой высоты.
Таким образом, два модификатора не конфликтуют друг с другом — они работают в паре.
.fixedSize определяет, какой должна быть высота: ровно такой, чтобы вместить самую высокую карточку. .frame(maxHeight: .infinity) определяет, как остальные карточки должны вести себя по отношению к этой высоте: полностью её заполнить.
Уберите любой из них — и всё перестанет работать. Без .fixedSize стек растянется на весь экран. Без .frame(maxHeight: .infinity) короткие карточки останутся короткими, и строка снова будет неровной.
Задача решена ✅
Главный урок
Признаюсь честно: на поиск решения у меня ушло около полутора часов.
Не потому, что само решение сложное — это буквально одна строка. Просто я постоянно обходил .fixedSize стороной и не хотел его пробовать. Мой мозг уже пометил этот модификатор как «опасный» и отказывался пересматривать такую оценку.
Проблема была не в сложной компоновке. Я сам ограничил собственный набор инструментов.
В следующий раз, когда поймаете себя на мысли «я никогда не использую этот модификатор», остановитесь и спросите себя почему. Если ответ звучит как «у него пугающее название» или «я когда-то прочитал сообщение, где советовали его избегать», это не настоящая причина.
Каждый модификатор SwiftUI существует потому, что кто-то в Apple столкнулся с задачей компоновки, которую он решает. Ваша задача — понимать, для какой проблемы предназначен каждый инструмент.
Не ограничивайте возможные решения. Ответ может находиться прямо перед вами — просто под названием, которое вы привыкли игнорировать 😅
-
Интегрированные среды разработки3 недели назадАналоги Cursor для разработчиков: что выбрать для работы с кодом
-
Разработка4 недели назад10 советов, как получить максимум от Claude Code в iOS-разработке
-
Новости4 недели назадВидео и подкасты о мобильной разработке 2026.28
-
Новости3 недели назадВидео и подкасты о мобильной разработке 2026.29
