init coder aDecoder는 정확히 무엇입니까?


122

온라인 코스에서 iOS 개발을 배우고 있으며 사용자 정의보기 (사용자 정의 테이블보기 셀, 컬렉션보기 셀 등)를 만들 때마다 강사는 항상이 초기화 프로그램을 구현합니다.

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

왜 항상 이것을 불러야합니까? 그것은 무엇을합니까? init 안에 속성을 넣을 수 있습니까?


5
이 대답은 당신을 도울 것입니다 stackoverflow.com/questions/24036393/...이 주셔서 감사합니다
Seungyoun 이순신

2
를 구현하는 객체를 서브 클래 싱하는 NSCoding경우이 이니셜 라이저를 구현해야합니다 NSCoding.. 최소한 수퍼 클래스 init 메소드를 호출해야합니다. 에 NSCoder클래스에 대한 인코딩 된 속성 이 포함 된 경우이 메서드를 사용하여 복구 할 수 있습니다
Paulw11

1
또한 Apple의 공식 Swift 책에서 객체 초기화에 대한 섹션을 읽어 보는 것이 좋습니다.
Nicolas Miari

답변:


121

이 대답은 반대 방향에서 시작하겠습니다.보기 상태를 디스크에 저장하려면 어떻게해야합니까? 이것을 직렬화라고 합니다. 역 직렬화 는 디스크에서 개체의 상태를 복원하는 것입니다.

NSCoding프로토콜은 직렬화 및 역 직렬화 객체에 대한 두 가지 방법을 정의한다 :

encodeWithCoder(_ aCoder: NSCoder) {
    // Serialize your object here
}

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}

그렇다면 사용자 정의 클래스에 왜 필요한가요? 정답은 Interface Builder입니다. 개체를 스토리 보드로 끌어서 구성하면 Interface Builder는 해당 개체의 상태를 디스크에 직렬화 한 다음 스토리 보드가 화면에 나타날 때 역 직렬화합니다. 이를 수행하는 방법을 Interface Builder에 알려야합니다. 최소한 서브 클래스에 새 속성을 추가하지 않으면 수퍼 클래스에게 패킹 및 언 패킹을 super.init(coder: aDecoder)요청 하여 호출 할 수 있습니다. 하위 클래스가 더 복잡한 경우 하위 클래스에 대한 자체 직렬화 및 역 직렬화 코드를 추가해야합니다.

이는 런타임에 개체를 만들기 위해 숨겨진 파일에 코드를 작성하는 Visual Studio의 접근 방식과는 대조적입니다.


awakeFromNib 안에 모든 것을 넣고 사용하는 것을 잊는 것은 init(coder aCoder : NSCoder)어떨까요?
Honey

@Honey-한마디로 "때로는 그렇게 할 수 없습니다". 일반적으로 항상 그런 것은 아닙니다.
Fattie

@Fattie는 그것을 알기에는 너무 복잡하거나 불필요하지 않은 세부 사항입니까? 설명해 주시겠습니까?
Honey

9
Interface Builder에서 개체를 구성하려면 @Honey가 awakeFromNib작동하지 않습니다. 런타임에awakeFromNib 호출됩니다 . Interface Builder에서 수행하는 모든 작업은 디자인 타임 입니다. 디자인 타임 에서 수행 한 작업 을 실행 시간 으로 옮기는 것은 (저장) 및 (로드)입니다.encodeWithCoderinit(coder:)
Code Different

3
당신이 (즉, 코드로 프로그래밍을 할) 사용자 정의 클래스를 구성하는 인터페이스 빌더를 사용하지 않는 경우 @Honey은 당신은 그것을 할 수 있습니다 awakeFromNib또는initWIthFrame
다른 코드

28

이 초기화 프로그램을 구현하기위한 요구 사항은 다음 두 가지 결과입니다.

  1. Liskov 대체 원칙 . S가 T의 하위 클래스 (예 : MyViewController의 하위 클래스 ViewController)이면 S 개체 (의 인스턴스 MyViewController)는 T 개체 (의 인스턴스 ViewController)가 예상되는 위치에서 대체 될 수 있어야합니다 .

  2. 이니셜 라이저가 서브 클래스에 명시 적으로 정의 된 경우 Swift에서 이니셜 라이저가 상속되지 않습니다. 하나의 이니셜 라이저가 명시 적으로 제공되면 다른 모든 이니셜 라이저가 명시 적으로 제공되어야합니다 (그런 다음을 호출 할 수 있음 super.init(...)). 근거는 이 질문 을 참조하십시오 . Java에 있지만 여전히 적용됩니다.

요점 1에서는 원본이 ViewController할 수있는 모든 것을 MyViewController서브 클래스가 할 수 있어야합니다. 그러한 것 중 하나는 주어진에서 초기화 될 수 있다는 것입니다 NSCoder. 포인트 2에서는 MyViewController하위 클래스가이 능력을 자동으로 상속하지 않습니다. 따라서이 요구 사항을 충족하는 이니셜 라이저를 수동으로 제공해야합니다. 이 경우 일반적으로 수행하는 작업을 수행하려면 수퍼 클래스에 위임하기 만하면됩니다.


1
생성자가 상속되지 않는다는 것은 완벽합니다. 기본 클래스의 (상속 된) 이니셜 라이저를 사용하여 파생 클래스의 인스턴스를 초기화하는 경우 파생 클래스에 의해 새로 정의 된 ( "추가 된") 상속되지 않은 속성은 초기화됩니다.
니콜라스 미아리

3
사실, 이니셜 라이저는 스위프트에서 상속됩니다. 서브 클래스에 자신 만의 이니셜 라이저 구현을 제공하지 않는다면 말입니다. 새로 정의 된 상속되지 않은 속성에 기본값이있는 경우 하위 클래스에 이니셜 라이저를 작성하지 않고 모든 수퍼 클래스의 이니셜 라이저를 상속 할 수 있습니다. 참조 여기
TheBaj
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.