Swift

loadView()에 대한 간단한 고찰

hyeonii_12 2020. 11. 20. 18:56
반응형

LoadView에 대한 간단한 고찰

Swift Version 5.3
Xcode Version 12.2

 

ifkakao 2020을 보면서 카카오는 어떻게 일하는 지 어떻게 개발하는 지 많은 눈팅을(ㅎ__ㅎ) 했습니다.

관련 세션을 보다가 눈에 띈 것이 바로 loadView() 입니다.
저는 평소에 뷰 컨트롤러에 화면을 그릴 때 viewDidLoad() 함수를 많이 쓰는데 카카오는 왜 loadView를 쓰는 지 궁금해져서 간단하게 알아보겠습니다.

우선 모를 때는 공식 문서 먼저..

loadView가 뷰를 만드는(create) 메서드고, viewDidLoad가 말 그대로 뷰가 메모리에 로드 되고 난 후에 불리는 메서드니까
loadView가 viewDidLoad 보다는 먼저 호출되나?

1
2
3
4
5
6
7
8
9
10
11
12
class ViewController: UIViewController {
    
    override func loadView() {
        super.loadView()
        print("loadView()")
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        print("viewDidLoad()")
    }
}
cs

정답!

viewDidLoad나 다른 함수들에서 사용했던 것처럼
super.loadView() 를 사용했는데 개발 문서에 아래와 같은 글이 있었습니다..

Your custom implementation of this method should not call super.

왜인지는 모르겠지만.. 일단 하라는 대로 합니다..

super가 아니라 뷰를 직접 만들어주어야 합니다.

1
2
3
4
override func loadView() {
    self.view = .init() // UIView()
    print("loadView()")
}
cs

뷰를 새로 그려서 현재의 뷰 컨트롤러의 루트 뷰에 지정을 해 줍니다.
네, 여기까지는 이해가 된 것 같아요!

그렇다면 인터페이스 빌더로 뷰 컨트롤러를 만들어서도 확인을 해 볼까요?

If you use Interface Builder to create your views and initialize the view controller, you must not override this method.

라고는 하지만...

제가 직접 만들어 본 결과 실행은.. 되더라구요!
must not 이라고 이야기 한 거 보면 crash가 나야할 것 같은데 왜 되는 지 모르게쑴....

그래도 실행은 되니까 알아보자면,
인터페이스 빌더에서 loadView를 사용한다면

1
self.view = .init()
cs

이 아니라

1
super.loadView()
cs

를 사용해야 합니다.

그래야 인터페이스 빌더에서 그린 화면이 잘 나오기 때문이죠!
뷰를 새로 그려주면 인터페이스 빌더의 내용은 나오지 않게 됩니다.

이렇게 뷰의 배경색을 노란색으로 지정해 놓고 self.view = .init() 을 사용해서 실행을 하게 되면

네 아무런 소식이 없습니다..
그렇다면 super.loadView()로 바꾸면 어떻게 될까요?

오! 잘 나오네요!

하나만 더 테스트를 해 보겠습니다.
인터페이스 빌더에서 그린 뷰와 클래스 파일에서 그린 뷰 중 어느 것이 나중에 그려질까요?

이렇게 인터페이스 빌더 위에 뷰를 하나 올려놓고,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ViewController: UIViewController {
 
    public override func loadView() {
        super.loadView()
        
        let greenView = UIView()
        greenView.backgroundColor = .green
        
        self.view.addSubview(greenView)
        greenView.translatesAutoresizingMaskIntoConstraints = false
        greenView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
        greenView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 50).isActive = true
        greenView.widthAnchor.constraint(equalToConstant: 100).isActive = true
        greenView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    }
 
    public override func viewDidLoad() {
        super.viewDidLoad()
    }
 
}
 
cs

이렇게 초록색 뷰를 하나 그려서 실행해보겠습니다!

네! 인터페이스에서 그린 뷰 위에 새로운 뷰가 나오는 것을 볼 수 있습니다.

공식 문서에서

If the view controller has an associated nib file, this method loads the view from the nib file.

라고 했으니 super.loadView() 를 통해서 인터페이스의 뷰를 그리고 그 이후에 해당 메서드가 실행되어서 그런 것 같습니다!

근데 공식 문서에서 쓰지 말라고 하니까 일단 안 쓰는 걸로.....ㅎㅎㅎㅎ

 

결론

1. loadView()는 뷰 컨트롤러에서 루트 뷰를 그리는 메서드이고, viewDidLoad() 보다도 더 먼저 실행된다.

2. loadView()에서는 뷰를 직접! 초기화 해주어야 한다.

3. loadView()는 코드로 직접 뷰 컨트롤러를 그리는 경우에만 사용해야 한다.

 

혹시
1. 왜 뷰 컨트롤러를 코드로 직접 구현하는 경우에 super를 부르면 안 되는지,
2. 왜 인터페이스 빌더에서 그린 뷰 컨트롤러의 클래스 파일에서 loadView 메서드를 오버라이드 하면 안 되는지
아시는 분이 있으시다면 댓글로 알려주세요!!

반응형