teunteun2
[Swift] required init?(coder: NSCoder) & override init(frame: CGRect) 본문
[Swift] required init?(coder: NSCoder) & override init(frame: CGRect)
teunteun2 2022. 4. 6. 17:25
UiView를 상속받아 Custom Class를 만들 때 우리는 생성자를 통해 뷰를 구성해야하기 때문에
required init?(coder: NSCoder) override init(frame: CGRect) 이 두 생성자를 만나게 되는데요,
오늘은 이 두 생성자의 차이점과 함께 코드로 뷰를 구성할 때 두 생성자를 모두 호출해야하는 이유에 대해서 정리해보았습니다
required init?(coder: NSCoder)
XIB는 XML Interface Builder의 약자로, Xcode 컴파일로는 번역할 수 없습니다
그래서 XIB를 nib으로 변경하여 Xcode 상에서 컴파일 할 수 있도록 만드는 과정이 필요한데요 ~
여기서 nib을 통해 컴파일하고 해체하는 과정을 unarchiving / deserialize 라고 하며
이 과정을 도와주는 것이 바로 NSCoder 라는 프로토콜이에요
결론적으로 Storyboard, XIB와 같은 인터페이스 빌더를 통한 뷰를 구성할 땐 NSCoder를 매개변수로 갖는 init? 생성자가 내부적으로 호출된답니다
근데 우리가 init?(coder: NSCoder) 생성자를 오버라이딩 할 때 앞에 required가 붙잖아요 ?
이건 NSCoding이 프로토콜로 정의되어 있고 NSCoding 내에 init? 생성자가 포함되어 있기 때문인데요,
프로토콜에서 언급된 프로토콜 초기화 함수는 반드시 구현해야하기 때문에 구현 시 앞에 required를 붙여주는 것입니다
이번엔 코드로만 뷰 혹은 셀을 구성할 경우를 볼까요?
override init(frame: CGRect)
override init(frmae:CGRect)는 XIB, Storyboard 와 같은 인터페이스 빌더를 사용하지 않고 코드로 뷰를 구성할 때 사용하는 생성자인데요, 코드로 뷰를 구성할 때 지정생성자 init(frame: CGRect)만 오버라이드 해서 뷰를 구성하면 된다고 생각이 들지만
!항상! required init?(coder:NSCoder)를 함께 호출해주어야 합니다. 안하면 에러가 나요 ..
왜그럴까요 ?
앞서 말햇듯 init?(coder:NSCoder)은NSCoding 프로토콜 내에 정의되어 있는 생성자이기 때문에
꼭 구현해야하기 때문이에요
Swift에선 자식클래스에서 지정 생성자를 작성하지 않으면, 부모클래스의 생성자를 자동으로 상속하기 때문에
인터페이스빌더를 통해 뷰를 생성해줄 땐 init이 없어도 UIView 내부에 있던 생성자가 상속되어 에러가 나지 않았던 겁니다!
하지만 자식클래스에서 지정생성자를 작성하게 된다면 부모클래스의 생성자들이 더 이상 상속되지 않습니다
코드로 뷰를 구성할 땐 init(frame: CGRect)를 통해 프레임 초기화를 해야하기 때문에 우리는 지정생성자를 자식클래스에서 꼭 호출해야하죠 ? 그렇기 때문에 꼭 구현되어야 하는 init?(coder: NSCoder) 생성자가 자동 상속되지 않아 에러가 나는거랍니다
마지막으로 한가지 더 궁금한 것. 왜 init?(coder: NSCoder) 생성자는 옵셔널일까요 ?
NSCoding 프로토콜에 포함되어 있는 해당 생성자는 바로 실패 가능한 생성자이기 때문이에요,
그래서 우리는 코드로 뷰를 짤 때 함께 명시해주어야 하는 required init?(coder:NSCoder) 생성자 내부에
fatalError("init(coder:) has not been implemented")
위 문장과 같은 프린트 구문을 넣어줍니다
실패 가능한 이니셜라이저
생성자를 통해 뷰를 초기화 할 때, 이런저런 예외 상황 때문에 초기화를 실패할 경우가 생길 수도 있겠죠 ?
이럴 때 초기화 실패 가능성을 열어두기 위해 생성자가 초기화를 실패할 경우 nil을 반환하도록 만들어둘 수 있습니다.
하지만 생성자가 nil을 반환할 수 있게 된다면? 생성자 또한 옵셔널 타입이 되겠죠?
그래서 init?(coder:NSCoder)에 ?이 붙게 된 것입니다 : )
이렇게 실패 가능한 경우를 고려한 생성자를 실패 가능한 이니셜라이저 라고 부릅니다
다음에는 XIB로 커스텀 뷰 클래스를 만들 때 호출되는 awakeFromNib() 메서드와 생성자의 호출 시점에 대해 써보도록 할게요 ~ : )
'iOS' 카테고리의 다른 글
[iOS] Stack View 내의 Stack View 구조로 연습해보기 (1) | 2022.04.10 |
---|---|
[RxSwift] Observable & Observer & Dispose를 이해해보자 (0) | 2022.04.08 |
[Swift] Foundation, UIKit Framework에 대해 (+ UIViewController & UIView의 차이) (0) | 2022.03.16 |
[Swift] Cocoa Touch Framework | Cocoa | NSObject 에 대해 (0) | 2022.03.15 |
[Swift] iOS의 특징 4가지 (0) | 2022.03.14 |