이니셜라이저의 키워드에 관하여
[Swift] Initialization
Initializer 란? Initialize는 초기화라는 뜻입니다. 여기서 초기화라는 것은 모두 0값으로 보내버리는 ...
blog.naver.com
여기 완벽핟;;
아래는 따로 적고 싶은 내용 적어둠
Swift는 기본적으로 서브클래스가 수퍼클래스의 이니셜라이저들을 상속받지 않은 것을 원칙으로 하고 특별한 경우에 자동 상속을 허용한다.
이니셜라이저의 자동상속은 다음의 조건을 만족해야 한다.
1. 만약 자식 클래스에서 추가된 저장 프로퍼티가 모두 디폴트 값을 가지고 있고, 추가적인 지정 이니셜라이저를 작성하지 않았다면(여기서는 추가되는 지정이니셜라이저 혹은 지정이니셜라이저의 오버라이드가 모두 포함된다.) 부모 클래스의 모든 지정 이니셜라이저를 상속받는다.
2.부모의 이니셜라이저를 상속받았거나, 아니면 부모의 모든 지정 이니셜라이저를 오버라이드했다면 부모의 편의 이니셜라이저를 자동으로 상속받는다.
Designated Initializers vs Convenience Initializers
1. Designated Initializers(지정 이니셜라이저)
클래스의 주 이니셜라이저는 지정 이니셜라이저로, 클래스의 모든 속성을 완전히 초기화한다.
적합한 슈퍼클래스 이니셜라이저를 호출하여 초기화 과정을 부모클래스로 연쇄하도록 한다.
모든 클래스는 하나 이상의 지정 이니셜라이저를 가진다.
지정 이니셜라이저는 깔때기를 통해 초기화 과정의 연쇄를 슈퍼클래스로 진행시킨다.
2. Convenience Initializers(편의 이니셜라이저)
편의 이니셜라이저는 호출하는 지정 이니셜라이저 인자에 기본 값으로 설정할 수 있다.
또한 특정 쓰임새나 입력 값 타입을 위한 클래스의 인스턴스를 생성하기 위해 편의 이니셜라이저를 정의할 수 있다.
만약 클래스에 편의 이니셜라이저를 쓸 필요가 없다면 사용하지 않아도 된다.
일반적인 이니셜라이저 패턴을 단축할 때 만든 편의 이니셜라이저는 시간을 단축시키거나 클래스의 이니셜라이저 의도를 명확하게 만들 수 있다.
이니셜라이저 연쇄(Initializer Chaining)
지정 이니셜라이저와 편의 이니셜라이저의 관계를 간단하게 하기 위해 Swift는 다음 세가지 규칙을 적용하였다.
- 규칙 1. 지정 이니셜라이저는 직접 관련있는 슈퍼클래스로부터 지정 이니셜라이저를 호출해야 한다.
- 규칙 2. 편의 이니셜라이저는 같은 클래스에서 다른 이니셜라이저 호출해야 한다.
- 규칙 3. 편의 이니셜라이저는 지정 이니셜라이저로 끝맺어야 한다.
흐음...
편의 이니셜라이저는 같은 클래스에 있는 다른 이니셜라이저를 불러내고 <- 셋팅을 편하게 하기위해?
지정 이니셜라이저는 상위 클래스의 지정 이니셜라이저를 호출해야하네.. <- 셋팅을 확실하게 하기위해?
Required Initializers
view와 viewController에서 출몰하는 required init(coder: NSCoder)는 무엇이냐..
아래 처럼 view와 viewController는 NSCoding 프로토콜을 채택함
즉 자식 클래스도 NSCoding 프로토콜이 채택된 상황임
NSCoding은 init(coder: NSCoder)은 필수적으로 구현해야하고 구현하는 클래스에서 required 키워드가 붙음(확인 완료)
init을 한개도 구현 안한다면
즉, 부모 클래스를 자동으로 상속받아서 required도 구현이 된 상태지만
하나라도 구현하거나, 자동 상속 조건을 만족안한다면 -> 더이상 required는 상속이 안되니깐 구현을 해줘야함!
참고로 storyBoard에서 만든 view, viewController는
아카이브(기록?)으로 구성한다고 한다. (decode를 보니 An unarchiver object.라고 함, 아카이브를 정확히 어떤 형태로 하냐구 ㅜㅜ)
-> xml로 기록하는 거 같은데?
-> 흠 번역해보자
-> UIStoryboard object는 아카이브된 버전의 뷰 컨트롤러들을 관리한다.
-> 디자인하고 있을 때, 앱 번들에 있는 스토리보드(base)에 저장함
-> 엑스코드는 데이터를 재생성되어야하는 형태로 저장한다(아카이브를 뜻하는 듯, encoder 이용)
-> 초기화 과정에서 언아카이브하고, init(coder:)을 이용해 프로그래밍적으로 생성한다(decoder 이용)
아~ xml로 기록함(소스 제어 관리 시스템이 있어서) -> 이때 커스텀 클래스도 xml로 아카이브 됨(IB inspector값이 우선인듯?) -> 빌드시 NIB로 변환 -> 초기화시 init(coder:) 이용해서 언아카이브! -> 그러나 다른 뷰들이 생성중이고 and 아직 뷰의 프레임을 정확히 구할 수 없음 + IBOutlet도 당연히 쓸수 없음, 왜냐 아직 다른 뷰들은 안 만들어졌을 수도 있거덩
-> 아카이브의 모든 객체가 로드되고 초기화된 이후에, nib-loading 인프라스트럭처는 nib archive로부터 재생성된 각 객체에게 awakeFromNib 메시지를 보낸다. 객체가 awakeFromNib 메시지를 수신할 때, 모든 outlet과 action 연결(connection)이 이미 설정됐음을 보장한다. 준비가 되었음을 보장한다(즉 모든 뷰가 객체화 된 상태다!)-> awakeFromNib(함수 안에서 추가적인 초기화가 가능하다고 함!, 그러나 iboutlet, ibaction와 관련된건 초기화 불가능)
아래는 부연 설명
awakeFromNib()
- 스토리보드로 생성시 호출되는 함수(코드로 생성된 뷰는 X)
- Interface Builder에서 객체가 init(coder:)로 초기화(인스턴스화)된 후 호출
- IB에서 inspector와 같은 방법으로 값을 조정하면 위 커스텀 클래스는 아카이브되어 있다가 언아카이브로 변화 되는데,
(이 때 init(coder:)가 호출되며 내부 속성이 초기화 -> init시점에는 frame과 관련된 크기, 위치 등이 정해지지 않은 상태) - 위 단계에서 IB는 연결된 객체의 변수를 사용하려고 할 때 awakeFromNib()을 사용
* XIB: XML Interface Builder, "flat file" (아무런 구조적 상호관계가 없는 레코드들이 모여있는 파일)
* NIB: NeXT Interface Builder (빌드시, XIB가 NIB로 변환)
- 처음부터 NIB로 저장하면 될 것을, XIB로 저장하는 이유?
XIB가 SCM(source control management : 소스 제어 관리)시스템에 유리하기 때문