🤿 딥다이브

[iOS, UIKit] UIView는 인자없이 초기화가 가능한데, 왜 UIView를 상속받으면 인자없이 초기화가 안될까?

PushedGun 2023. 10. 22. 15:18

1. 문제 상황

작업중 UIView를 상속받은 커스텀 뷰를 만드는 과정에서 super.init()을 호출할 경우 오류가 발생하여 UIView()는 어떤 이니셜라이저를 호출하는지 의문이 생겨 찾아보았다.

class customView: UIView {
    init() {
        super.ini() //여기서 에러가 발생함. UIView는 UIView() 이렇게 초기화를 할 수 있었는데 대체 왜지??
    }
}

2. 혹시 UIView에 convenience init()이 있나?

구글링을 해보니 어느 블로그에서는 UIView()가 NSObject의 init()을 호출한다고 하였다.

그런데 아래와 같은 근거로, 이렇게 동작하지는 않는다고 판단하였다.

  • superclass(NSObject)에서 subclass(UIView)의 designated init을 호출할 수 없다.

2023.10.22 - [iOS] - [iOS] designated init, convenience init 은 대체 뭘까??

 

[iOS] designated init, convenience init 은 대체 뭘까??

아주 간단히 요약하자면, 다음과 같다. 1. designated init(지정 생성자) 초기화에 반드시 필요한 생성자이다. 무조건 designated init이 불려야 객체가 생성된다. 2. convenience init(보조 생성자) 초기화에 반

pushedgun.tistory.com

 

  • 위 내용대로 동작할 경우 커스텀 뷰의 이니셜라이저에서 super.init()에서 에러가 발생하지 않아야 한다.

UIView에 convenience init()이 존재하고 그 속에서 self.init(frame: CGRect)를 호출한다는 결론을 내리니 모든 현상이 설명되는 것처럼 보였다.

 

super.init()에서 에러가 발생하는 이유

  • UIView의 이니셜라이저는 init(frame: CGRect), init(coder: NSCoder) 두 가지이다.
  • subclass에선 superclass의 convenience init()를 호출할 수 없다. 따라서 UIView를 상속받은 커스텀 뷰는 UIView의 convenience init()을 호출할 수 없기 때문에 super.init()을 호출할 수 없다.

 

super.init()이 컴파일 시간에는 에러가 발생하지 않고, 런타임 시간에만 에러가 발생하는 이유

  • UIView가 상속받는 superclass 중 NSObject에 init()이 존재하기 때문에 super.init()에서 컴파일 에러가 발생하지 않았다.

 

참고 링크 : https://stackoverflow.com/questions/39952355/how-come-i-can-initialize-a-uiview-without-parameters-but-its-documentation-doe

 

How come I can initialize a UIView without parameters, but its documentation does not have an empty initializer?

let view = UIView() Why does this compile without an error when the only documented UIView initializer is init(frame: CGRect)? Specifically, I am trying to write a new class that inherits from UIV...

stackoverflow.com

 

3. 결론: swift compile가 UIView는 인자없이 초기화가 가능하도록 init()을 생성해주었던 것이다.

콜 스택을 통해 확인해보니, @nonobjc 코드가 생기며, @objc init(frame:)이 불리는 것을 확인할 수 있다.

컴파일러가 인자없이 생성이 가능하도록 init()을 만들어주었던 것이다.

 

사실 이렇게 콜 스택을 통해 검증하는 방법이 익숙하지 않아서, 가지고 있던 지식들만을 활용해서 여러 가설들을 세웠었다.

무언가 그 원인을 잘 모르겠을 때, 콜 스택을 확인해 직접 확인해주는 방법을 자주 활용해보아야겠다.