Ответ
Метод loadView вызывается системой один раз за время жизни контроллера при первом обращении к его свойству view. Однако он может быть вызван повторно, если система освободит вью из-за нехватки памяти.
Почему именно так?
Система iOS управляет памятью и может выгрузить view контроллера, который не отображается на экране (например, находящийся в фоне). При возврате к такому контроллеру система пересоздаст его view, снова вызвав loadView.
Пример реализации:
class CustomViewController: UIViewController {
override func loadView() {
// Создаём кастомное view вместо стандартного
let customView = UIView(frame: UIScreen.main.bounds)
customView.backgroundColor = .systemBackground
self.view = customView
print("loadView вызван")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// При нехватке памяти система может nil'ить view и позже пересоздать её
}
}
Ключевой момент: Не выполняйте в loadView работу, которая должна быть однократной (например, добавление сабвью-контроллеров). Для этого используйте viewDidLoad.
Ответ 18+ 🔞
А, ну это же классика, блядь! Система iOS, сука, как хитрая жопа — она с loadView вытворяет такие финты, что диву даёшься.
Смотри, в теории этот метод вызывается один раз, когда впервые кто-то потрогает твой view. Ну, типа, родился контроллер, живёт, красавец. Но система-то, эта мартышлюшка, она жадная до памяти, понимаешь? Если твой контроллер ушёл на второй план, а памяти стало мало — она может взять и выгрузить его вьюху нахуй, чтобы место освободить. Просто view = nil, и всё.
А потом, когда пользователь возвращается обратно, системе надо же view показать! И она, такая: «Опа-па! А view-то нету!». И тогда она снова, блядь, дергает твой loadView, чтобы пересоздать всё с нуля. Вот и получается, что «один раз» — это не железобетонно. Это «один раз за один цикл жизни вьюхи», а циклов этих может быть несколько, если память поджимает.
Запомни, как отче наш: В loadView ты только создаёшь и присваиваешь своё кастомное вью. Всё. Точка. Никакой лишней хуйни!
Не вздумай там сабвью-контроллеры пихать или данные грузить — для этого есть viewDidLoad, который вызывается после того, как вьюха создана и готова к работе. А если ты в loadView наворотишь логики, которая должна быть однократной, то при повторном вызове из-за нехватки памяти тебе пиздец — всё продублируется, и будет тебе счастье.
Смотри, как правильно, без косяков:
class CustomViewController: UIViewController {
override func loadView() {
// Только создаём вьюху и присваиваем. Никаких плясок с бубном!
let customView = UIView(frame: UIScreen.main.bounds)
customView.backgroundColor = .systemBackground
self.view = customView
print("loadView вызван — вьюха родилась (или переродилась)")
}
override func viewDidLoad() {
super.viewDidLoad()
// А вот тут уже безопасно настраиваем: добавляем кнопки, грузим данные, пихаем child-контроллеры.
setupSubviews()
loadInitialData()
print("viewDidLoad — всё готово к показу")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Вот тут система может тебе намекнуть: «Чувак, память кончается, я щас твою вьюху в тартарары спущу».
// Будь готов, что view обнулится и потом loadView вызовут снова.
}
}
Короче, суть в чём: loadView — это про рождение и перерождение самой вьюхи. Всё остальное — не его ебать дело. Держи логику раздельно, и будет тебе счастье, а не волнение ебать.