Custom View 생성시 init(frame:), init(coder:), awakeFromNib()

jane·2022년 6월 2일
0

iOS

목록 보기
21/32

init(frame:), init(coder:)

UIView를 상속받은 커스텀뷰를 생성할 때 UIView의 필수 생성자 두개를 작성해야한다.

  • init(frame: CGRect) → 코드로 뷰를 만들 때 호출됨
  • init(coder: NSCoder) → 스토리보드/nib로 뷰를 만들 때 호출됨

요기 UIView의 정의부분을 보면 생성자 두개가 있음

class MyCustomView: UIView {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        custominit()
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        titleLabel.text = "수정함"
        titleLabel.textColor = .blue
        descriptionLabel.text = "엥"
    }
    
    
    func custominit() {
        if let view = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? UIView {
            view.frame = self.bounds
            addSubview(view)
        }
    }
}

awakeFromNib()

그리고 awakeFromNib()는 XIB로 만든 커스텀 뷰에서 인터페이스 빌더에서 연결된 객체를 설정할때 사용한다.

우리가 흔히 UIViewController에서 초기 화면 설정할때 사용하는 viewDidLoad() 와 비슷한 개념이라고만 알고 있었다. 도대체 뭔지 한번 알아보자.

호출 시점

언제 호출되냐면 Nib/Xib 파일이 언아카이브되고 나서 init(coder: NSCoder)로 모든 객체가 초기화가 완료되었을 때 호출된다.

*빌드시 xib가 nib로 전환된다

모든 객체가 초기화완료된다는 것의 의미는… 예를 들어 뷰가 서브뷰에 대한 참조를 가지고 있을수도 있고, 뷰의 참조를 설정하는 것은 한번에 하나씩 이루어지므로 전체적인 로딩 과정이 끝나지 않은 경우 이니셜라이즈가 안된 객체가 있을수도 있다.

그런데 이게 불리면 확실히 뷰의 모든 객체가 이니셜라이즈 된 것이라고 보면 된다.

그리고, 아카이브의 모든 객체가 로드되고 초기화된 이후에, nib archive로부터 재성성된 각 객체에게 awakeFromNib 메세지를 보낸다.

따라서 참조된 객체가 awakeFromNib 메세지를 수신할 때, 모든 IBOutlet과 IBAction연결되어 접근이 가능한 상태이다.

따라서 뷰의 추가적인 설정이 필요한 경우 여기서 한다.

+추가적으로…

하지만, 뷰컨의 awakeFromNib() 시점에는 IBOutlet에 접근이 불가하다. 왜냐하면 뷰컨과 뷰컨이 가진 서브뷰의 Nib 파일이 분리되어있어서 그렇다.

뷰컨의 nib는 top-level object nib로서 이것만 로딩하고 서브뷰의 nib은 로딩하지 않은 채로 awakeFromNib()를 전달한다.

서브뷰의 nib파일은 이후 loadView() 메서드에서 비로소 로드된다고 한다.

Reference

https://velog.io/@yohanblessyou/스토리보드의-요소가-Nib이-되는-과정-feat.-awakeFromNib

profile
제가 나중에 다시 보려고 기록합니다 ✏️

0개의 댓글