iOS에서 ViewController의 생명주기는 화면(ViewController)이 생성되고 소멸될 때까지의 일련의 단계로 이루어진다. 이를 통해 ViewController가 화면에 표시되기 전후로 적절히 준비하거나, 정리 작업을 수행할 수 있다. 주요 생명주기 메서드와 함께 단계별로 설명하면 다음과 같다.
init(coder:)
또는 init(nibName:bundle:)
loadView()
view
가 생성될 때 호출됨viewDidLoad()
view
가 메모리에 로드된 후 호출됨viewWillAppear(_:)
viewIsAppearing(_:)
(iOS 13 이상)viewWillAppear(_:)
와 viewDidAppear(_:)
사이의 동작을 보완함override func viewIsAppearing(_ animated: Bool) {
super.viewIsAppearing(animated)
print("The view is currently appearing on the screen.")
}
viewDidAppear(_:)
viewWillDisappear(_:)
viewDidDisappear(_:)
didReceiveMemoryWarning()
deinit
init(coder:)
→ loadView()
→ viewDidLoad()
viewWillAppear(_:)
→ viewIsAppearing = true
viewIsAppearing(_:)
(iOS 13 이상)viewDidAppear(_:)
→ viewIsAppearing = false
viewWillDisappear(_:)
viewDidDisappear(_:)
didReceiveMemoryWarning()
(OLD) → deinit
loadView()
는 기본적으로 스토리보드나 XIB 파일에서 뷰를 자동으로 로드하지만, 코드 기반으로 UI를 작성할 때 직접 재정의하여 뷰 계층 구조를 생성해야 한다.
loadView()
의 역할view
속성)를 생성하는 메서드loadView()
를 재정의하여 뷰 계층 구조를 코드로 생성함:
override func loadView() {
// 기본 뷰 생성
let rootView = UIView()
rootView.backgroundColor = .white
// UI 요소 추가
let label = UILabel()
label.text = "Hello, World!"
label.textAlignment = .center
label.frame = CGRect(x: 50, y: 100, width: 200, height: 50)
rootView.addSubview(label)
// ViewController의 view에 설정
self.view = rootView
}
뷰 계층 구조를 더 세부적으로 설정할 수도 있음:
override func loadView() {
let customView = CustomView() // 커스텀 뷰 생성
self.view = customView
}
super.loadView()
를 호출하면 안 됨
loadView()
는 뷰를 생성하는 책임이 개발자에게 있다는 가정하에 설계된 메서드이기 때문에, 부모 클래스의 구현을 호출하지 않음성능 최적화:
viewDidLoad()
에서 UI를 구성하는 것도 가능하다. 사실, 스토리보드 없이 코드로 UI를 작성할 때는 viewDidLoad()
에서 주로 작업하는 경우가 많다. UIKit에서는 이미 기본적으로 UIViewController
의 view
가 생성되기 때문에, viewDidLoad()
에서 그 뷰에 UI 요소를 추가하거나 설정하는 방식으로 충분히 구현할 수 있다.
loadView()
와 viewDidLoad()
의 차이점특징 | loadView() | viewDidLoad() |
---|---|---|
뷰 생성 여부 | view 를 직접 생성해야 함 | 이미 생성된 기본 view 를 사용 |
사용 시점 | view 가 처음 요청될 때 호출 | loadView() 이후 view 가 메모리에 로드된 후 호출 |
일반적인 사용 사례 | 코드로 루트 뷰를 완전히 커스터마이즈할 때 사용 | 기본 view 에 UI 구성 및 초기화를 추가할 때 사용 |
기본 구현 호출 여부 | super.loadView() 를 호출하지 않음 | super.viewDidLoad() 를 항상 호출해야 함 |
viewDidLoad
에서 UI 구성하기MainViewController
에서 viewDidLoad()
를 활용해 UI를 구성하는 방법은 다음과 같습니다:
import UIKit
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 기본 뷰 설정
view.backgroundColor = .white
// 라벨 생성
let label = UILabel()
label.text = "Hello, World!"
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 24)
label.translatesAutoresizingMaskIntoConstraints = false
// 버튼 생성
let button = UIButton(type: .system)
button.setTitle("Tap Me", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
// 뷰에 추가
view.addSubview(label)
view.addSubview(button)
// 오토레이아웃 설정
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 20),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
}
}
loadView
와의 비교loadView
에서 작업view
를 생성해야 하므로 반드시 self.view = customView
를 명시해야 함view
자체를 완전히 대체할 때 적합함viewDidLoad
에서 작업view
에 UI 요소를 추가하거나 레이아웃 설정만 하면 됨loadView
를 선택해야 할까?view
를 사용하고 싶지 않을 때loadView
에서 커스텀 뷰 생성override func loadView() {
let customView = MyCustomView() // Custom UIView
self.view = customView
}
viewDidLoad()
사용loadView()
사용viewDidLoad()
에서 UI를 구성하는 것은 완전히 유효하며, 간단한 UI 작업에서는 더 권장된다. 하지만 뷰 계층 구조를 완전히 새로 정의해야 하는 경우 loadView()
를 사용하는 것이 적합하다.
didReceiveMemoryWarning()
이 iOS 13 이상에서 잘 사용되지 않는 이유는 Apple의 메모리 관리 방식이 바뀌면서, 해당 메서드의 호출 빈도가 줄어들거나 실질적인 필요성이 감소했기 때문이다.
didReceiveMemoryWarning()
의 원래 목적didReceiveMemoryWarning()
의 사용 감소 이유iOS 13 이후, 시스템이 더 정교한 메모리 관리 메커니즘을 도입했다:
didReceiveMemoryWarning()
호출이 발생하지 않는 경우가 많아짐didReceiveMemoryWarning()
를 사용하는 대신 개발자는 AR 리소스를 정리하거나 재로드하는 전용 API를 사용하게 되었음didReceiveMemoryWarning()
의 필요성이 감소했음didReceiveMemoryWarning()
의 사용을 강조하지 않고, 대신 효율적인 메모리 관리 방법(예: 적절한 캐싱 정책, 리소스 사용 패턴)을 권장함didReceiveMemoryWarning()
가 호출되는 사례가 급격히 줄어들었다는 개발자들의 보고가 있음Apple은 didReceiveMemoryWarning()
대신, 다음과 같은 방식을 통해 메모리 사용을 관리하도록 권장함
NSCache
를 사용해 관리함NSCache
는 시스템 메모리 부족 시 자동으로 캐시를 제거함viewDidDisappear(_:)
에서 불필요한 리소스를 해제함Apple의 최신 문서에서는 didReceiveMemoryWarning()
가 더 이상 강조되지 않으며, 대신 아래와 같은 방식을 권장한다:
Apple 개발자 포럼 및 여러 커뮤니티에서도 iOS 13 이상에서 didReceiveMemoryWarning()
호출 빈도가 현저히 줄어든 사례가 많이 언급된다.