Programming/Swift

[iOS/Swift] Initialization

devssun 2018. 12. 13. 23:49
728x90
반응형

커스텀 클래스


init(coder:)

  • https://developer.apple.com/documentation/foundation/nscoding/1416145-init
  • Returns an object initialized from data in a given unarchiver
  • 스토리보드에서 초기화 메소드를 호출할 때 이 메소드를 호출한다.
  • 따라서 스토리보드에서 생성한 객체의 초기화가 필요한 경우 이 메소드에서 작성해준다.
  • parameter로 들어가는 NSCoder 타입은 스토리보드에서 자동으로 생성되는 값이다. 스토리보드를 이용하지않더라도 해당 메소드를 사용할 수는 있지만 실제로 NSCoder에 어떤 값이 들어가는지는 알기 어렵다.

init(frame:)

  • https://developer.apple.com/documentation/uikit/uiview/1622488-init
  • Initializes and returns a newly allocated view object with the specified frame rectangle.
  • 프로그래밍 방식으로 생성한 객체는 초기화 메소드를 호출할 때 이 메소드를 호출한다.
  • 따라서 스토리보드가 아닌 프로그래밍 방식이라면 이 메소드를 override하여 작성해주면 된다.

초기화 메소드


  • 스위프트에서 저장 프로퍼티의 자동 초기화는 옵셔널 타입으로 선언된 경우에만 제한적으로 허용 (var string: String?)
  • 스위프트에서 옵셔널 타입으로 선언되지 않은 모든 저장 프로퍼티는 인스턴스가 생성되기 전에 반드시 초기값이 설정되어야 함

멤버와이즈(Memberwise) 초기화 메소드

  • 구조체 타입은 내부적으로 정의된 초기화 메소드가 있다. 또 구조체는 기본 값을 가지고 있지 않아도 된다.
  • 아래 예제처럼 a, b만 선언하더라도 눈에 보이지 않는 초기화 메소드가 존재하게 된다.
struct Foo {
    var a: Int
    var b: Int = 0

    // 눈에 보이지 않는 초기화 메소드
    init(a: Int, b: Int) {
        self.a = a
        self.b = b
    }
}

클래스의 초기화 메소드
반면에 클래스는 멤버와이즈 초기화 메소드가 제공되지않는다. 하지만 저장 프로퍼티의 초기값을 모두 지정했다면 별도로 초기화 메소드를 정의할 필요는 없다.
프로퍼티 10개 중 1개에 초기값을 지정하지 않았다면 해당 프로퍼티에 기본값을 지정하기위한 초기화 메소드가 필요하게 된다.

class Boo {
    var x: Int = 0
    var y: String = "초기값"
}

let boo = Boo.init()  // 클래스 객체가 묵시적으로 지원하는 기본 초기화 메소드 init(), 생략가능

클래스 상속에서 초기화 메소드
클래스를 상속하면 부모-자식 관계가 생성되고 자식클래스는 부모클래스의 속성, 함수를 물려받아 사용할 수 있다.
부모의 초기화 메소드는 자식 클래스에 추가된 새로운 저장 프로퍼티를 초기화하지 못하므로 이를 그대로 상속받아 사용하는데 초기화되지 않는 저장 프로퍼티가 생길 수 있다.
이를 방지하기 위해 일반적으로 부모의 초기화 메소드는 자식 클래스에게 상속되지않는다.

이에 대한 문제점 두가지!

1. 부모 클래스가 자식 클래스에 새롭게 생긴 프로퍼티를 초기화 못하는 문제 발생  
 - 부모 클래스의 초기화 메소드에는 부모 클래스에서 생성한 저장 프로퍼티만 있기 때문  
2. 자식 클래스에서 새로 정의한 저장 프로퍼티만 초기화한다면 부모의 저장 프로퍼티가 초기화되지 않는 문제 발생
  • 매번 자식 클래스에서 부모 클래스의 모든 저장 프로퍼티를 찾아가며 초기화를 해줄 수도 없는 일!
    그래서 자식 클래스에서 자식에 새로 생성한 프로퍼티를 초기화 하고 부모 클래스의 초기화 메소드를 호출하는 방식으로 사용한다.
// 위에서 정의한 Boo 클래스를 상속하는 BooBaby 클래스  
class BooBaby: Boo {
    var z: Int

    override init() {
        self.z = 0    // 자식 클래스의 저장 프로퍼티 초기화
        super.init()  // 부모 클래스(Boo)의 초기화 메소드를 호출한다.
    }
}

let booBaby = BooBaby()
print("x : \(booBaby.x), y : \(booBaby.y), z : \(booBaby.z)")
  • 이번 예제에서는 Boo 클래스가 슈퍼 클래스이지만 Boo 클래스도 누군가의 자식클래스일 수도 있다.

  • Boo가 부모의 초기화 클래스를 호출하고, Boo 부모는 Boo 할머니의 초기화 클래스를 호출한다.

  • 호출관계를 따라 최상위 클래스에 이르는 모든 저장 프로퍼티가 차례로 초기화되는 결과가 만들어진다.

  • BooBaby -> Boo -> BooMom -> BooGrandMom -> … -> SuperBoo

  • 이를 초기화 메소드의 델리게이션(Delegation) 라고 부른다.


반응형