Ответ
Окончательные, актуальные размеры корневой вью (view.bounds) становятся известны в методе viewDidLayoutSubviews().
Почему именно здесь? Этот метод вызывается после того, как система:
- Рассчитала layout для всех subviews (включая корневую вью).
- Установила их окончательные frame (размеры и положение).
Особенности метода:
- Многократный вызов: Вызывается при каждом изменении layout (поворот устройства, изменение размера, обновление constraints).
- Используйте флаги для кода, который должен выполниться только при первом layout.
Пример получения размера вью:
private var isInitialLayoutDone = false
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Получаем окончательный размер корневой вью
let viewSize = view.bounds.size
print("View size: (viewSize)")
// Код для однократного выполнения после первого layout
if !isInitialLayoutDone {
isInitialLayoutDone = true
configureInitialLayoutBasedOnSize(viewSize)
}
}
Важно: В viewDidLoad() и viewWillAppear(_:) размеры вью могут быть неверными (например, равными размеру экрана в Storyboard, а не реальному).
Ответ 18+ 🔞
А, слушай, вот эта вся история с размерами вью — это просто пиздец, конечно. Ну то есть, ты в viewDidLoad заходишь, такой весь уверенный, берешь view.bounds и думаешь: «О, сука, ну вот же он, мой размер!». А на деле это просто какая-то хуйня из сториборда, а не реальные цифры. Овердохуища разочарования.
Так вот, чтобы не обосраться с этим, есть один волшебный метод — viewDidLayoutSubviews(). Вот тут-то, блядь, уже всё по-честному. Система уже всё посчитала, расставила, все сабвьюхи на свои места загнала и только потом, как милостиво, говорит: «На, мудила, вот твои окончательные размеры, можешь пользоваться».
Но есть нюанс, ёпта! Этот метод вызывается не один раз, а как заведённый — на каждый чих. Повернул устройство? Вызвался. Констрейнты поменял? Вызвался. Ребёнок чихнул в соседней комнате? Возможно, тоже вызовется, я уже нихуя не уверен. Поэтому если тебе нужно что-то сделать один раз и только после того, как размеры стали настоящими, то без флага — никак. Иначе твой код будет выполняться, как последняя мартышлюшка, на каждый поворот экрана.
Смотри, как это выглядит в деле, чтобы не быть хитрожопым:
private var isInitialLayoutDone = false // Флаг, чтобы не дрочиться по сто раз
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Вот сейчас размер — это правда, блядь
let viewSize = view.bounds.size
print("View size: (viewSize)") // Ну наконец-то, реальные цифры, ебать
// А это чтобы инициализацию свою ебанутую сделать только один раз
if !isInitialLayoutDone {
isInitialLayoutDone = true
configureInitialLayoutBasedOnSize(viewSize) // Вот тут уже работаем с честными данными
}
}
Короче, запомни: viewDidLoad и viewWillAppear — для них размеры вью это как кот, который сука собака, не поймёшь что. Всё настоящее происходит в viewDidLayoutSubviews. Главное — не наебнись с этим флагом, а то накрутишь логику так, что сам от себя охуеешь.