[Swift] UIView.init() 에 대하여

눼에? UIView()UIView의 initializer가 아니라구여?

naljin

--

안녕하세여 여러분. 흠 원래 required init?(coder: NSCoder) 에 대해 쓰려다가 또 딴 길로 새버렸네유. 이 내용은 다른 곳에서도 충분히 잘 설명되어있는 것 같아서 그건 TIL에 개인적으로 정리하기로 하고..!

지금까지 UIView() 잘 써오셨나요?? 거두절미하고 UIView의 문서에서 initializer 를 보자요.

맞아여 이렇게 두개예요. 읭?? 근데 나는 UIView() 이렇게도 써왔는데?!!?!?! 왜 init() 에 대한 설명은 없는겨..?

봐봐! 생성하려고 괄호 열면 떡하니 처음으로 나오는게 () 생성자라고!! 그럼 이건 도대체 뭐다??? 오늘의 주제는 이런 의문점으로부터 시작합니다

흠.. UIView의 문서에는 init() 을 코빼기도 찾아볼 수 없으니 Implemented by subclass 어쩌구저쩌구 써있는 설명으로 구글링을 해보자구요

오호.. 사실 얘는 NSObject의 이니셜라이저였군요! 🤔

UIView에서 얘를 사용할 수 있다는건 어쨌든 NSObject를 상속받고 있단거네 ?? ㅇㅇ 맞슴다. UIViewUIResponder 를 상속받고, 얘가 다시 NSObject 를 상속받고 있죠.

오호 ㅇㅋㅇㅋ! 그래도 init(frame:)init(coder:) 두 개만이 UIView의 Designated initializer (class를 위한 필수 initializer) 이기 때문에 UIView 를 생성하려면 이 둘 중 하나를 어디선가 반드시 호출해줘야겠져??

UIView() 로 뷰를 생성하면 내부적으로 init(frame:CGRect) 을 호출하게 됩니다.

이렇게 말한지.. 어언.. 반년이 흘렀네요? ㅎㅎ

저는 이걸 예전에 삽질하다가 알게 되었는데 진짜 그런지 아래와 같이 코드를 작성하고 CustomViewinit(frame:) 부분에 디버그 포인터를 찍어봅시다리

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let view = CustomView()
}
}


class CustomView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
print(frame)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

좌측 디버그 네비게이터에서 콜스택 찍히는걸 보면 정말 init(frame:) 을 호출하고 있쥬? 참고로 이때 찍힌 frame은 (0.0, 0.0, 0.0, 0.0)값을 가집니다

그럼 init(frame:) 으로 뷰를 생성한다면 어떻게 콜스택이 찍힐까요??

let view = CustomView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 100)))

오호.. 좀 더 짧네요. 두 단계정도 줄어드는 것 같아요. 자세히 살펴봅시다

viewDidLaod@objc CustomView.init(frame:) 사이에 init(frame:)으로 생성한 것은

  1. CustomView_allocationg_init(frame:)

를 호출하고

init() 으로 생성한 것은

  1. UIView._allocationg_init()
  2. @nonobjc UIView.init()
  3. -[UIView init]

를 호출하고 있네여

흠 근데 콜 스택 찍힌 부분을 보면 아이콘들이 커피 모양도 있고, 사람 모양도 있네요??? 뭐지?? 싶어서 찾아봤슴다.

사람 모양은 유저 코드, 커피 모양은 AppKit / UIKit 쪽 코드라는 거였군요! 쏘 신기..

그럼 AppKit / UIKit 쪽 코드이자, @objc CustomView.init(frame:)가 호출 되기 바로 전 단계인 -[UIView init] 에서 NSObjectinit 을 override 한 후 init(frame:) 을 호출하는 거려나??? 정도의 생각이 드네욤. 구현된 코드를 볼 수 없는 이상 뇌피셜이긴 하지만여 ㅎ_ㅎ

튼 오늘의 결론은 UIView()NSObject 의 initializer이고, 이렇게 UIView를 생성하면 frame은 (0.0, 0.0, 0.0, 0.0) 인 상태로 UIView의 Designated Initializer인 init(frame:) 이 호출된다! 입니다.

오늘의 글도 누군가에게는 도움이 되길 바라며 그럼 20000~~!

출처

--

--