반응형
Notice
Recent Posts
Recent Comments
Link
Today
Total
10-16 16:46
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
관리 메뉴

iOS 개발 기록 블로그

[Swift] 프로퍼티를 init 메서드에서 초기화, 선언 시 초기화 차이 본문

iOS

[Swift] 프로퍼티를 init 메서드에서 초기화, 선언 시 초기화 차이

crazydeer 2024. 9. 11. 15:22
반응형

 

에러 상황

final class StepView: UIView {
    
    // MARK: - Properties
    
    private var isFitnessAuthorized: Bool

    // MARK: - Initializer
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setupView()
        self.bindView()
        self.isFitnessAuthorized = PermissionManager.getPedometerAuthStatus()
    }
    
    // MARK: - Setup View
    
    private func setupView() {
		    ...
    }
    
    // MARK: - Binding
    
    private func bindView() {
		    ...
    }
}

위처럼 사용하면 아래 위치에서 컴파일 에러가 발생합니다.

self.isFitnessAuthorized = PermissionManager.getPedometerAuthStatus()

 

결론부터 말하자면 아래처럼 init() 메서등 안에 코드 위치를 바꿔야 합니다.

self.isFitnessAuthorized = PermissionManager.getPedometerAuthStatus() // 서브클래스의 프로퍼티 초기화
super.init(frame: frame) // 상위 클래스 초기화

서브클래스의 프로퍼티가 모두 초기화된 후에야 super.init() 을 호출할 수 있습니다.

이 규칙이 필요한 이유

Swift에서 클래스의 인스턴스는 메모리에 할당될 때, 상위 클래스와 서브 클래스가 함께 사용됩니다.

상위 클래스가 초기화되기 전에는 메모리의 구조가 완전히 준비되지 않았기 때문에, 서브클래스에서 프로퍼티에 접근하거나 초기화하는 것은 안전하지 않을 수 있습니다.

적용되는 상황 설명

  • isFitnessAuthorized는 StepView 클래스의 인스턴스 프로퍼티입니다.
  • Swift는 서브클래스(StepView)가 자신의 모든 프로퍼티를 완전히 초기화한 후에만 상위 클래스(UIView)의 초기화를 호출할 수 있도록 강제합니다.
  • 즉, super.init()을 호출하기 전에 서브클래스의 모든 프로퍼티가 초기화되어 있어야 합니다. 따라서 isFitnessAuthorized 같은 서브클래스의 프로퍼티는 반드시 super.init() 호출 전에 초기화되어야 합니다.

만약 super.init() 호출 전에 서브클래스의 모든 프로퍼티가 초기화되지 않으면 Swift 컴파일러는 에러를 발생시키며, 이 초기화 규칙을 강제합니다.

그렇다면 아래처럼 서브클래스의 프로퍼티 선언 시 초기화하는 경우와 동일할까?

비슷해 보이지만, 중요한 차이점이 있습니다.

1. 프로퍼티 선언 시 초기화

private var isFitnessAuthorized: Bool = PermissionManager.getPedometerAuthStatus()
  • 장점: 이 방식은 프로퍼티 선언과 동시에 값을 설정할 수 있기 때문에 코드가 간결합니다.
  • 동작 원리: 선언과 동시에 값이 할당되므로, 해당 프로퍼티는 클래스의 모든 초기화 메서드에서 동일한 방식으로 초기화됩니다. 즉, 프로퍼티는 인스턴스가 생성될 때마다 자동으로 PermissionManager.getPedometerAuthStatus()의 결과로 초기화됩니다.
  • 주의 사항: 초기화할 때마다 함수가 실행되므로, getPedometerAuthStatus()의 결과에 의존해야 할 경우 해당 함수가 언제 호출되는지 예측하기 어려울 수 있습니다.

2. init에서 초기화

private var isFitnessAuthorized: Bool

override init(frame: CGRect) {
    self.isFitnessAuthorized = PermissionManager.getPedometerAuthStatus()
    super.init(frame: frame)
}
  • 장점: 이 방식은 init에서 프로퍼티를 명시적으로 초기화하므로, 초기화 시점을 명확하게 제어할 수 있습니다. 즉, super.init()을 호출하기 전, 특정 조건이나 로직을 기반으로 프로퍼티에 값을 할당할 수 있습니다.
  • 동작 원리: 클래스가 초기화될 때마다, init 메서드 안에서 직접 값을 할당합니다. 이는 커스텀 초기화 로직을 포함할 수 있으므로, 더 유연한 처리가 가능합니다.
  • 주의 사항: 프로퍼티가 초기화되는 시점이 init 메서드 내에서 명시적으로 설정되기 때문에, 프로퍼티의 초기화 순서를 조절하거나 초기화 로직을 다르게 만들 수 있습니다.

차이점 요약

  1. 초기화 시점
    • 프로퍼티 선언 시 초기화: 클래스가 인스턴스화될 때, 프로퍼티는 선언과 동시에 초기화됩니다. 이 방식은 모든 초기화 경로에서 동일한 방식으로 초기화됩니다.
    • init에서 초기화: 프로퍼티는 클래스 초기화 과정에서 명시적으로 초기화됩니다. 여기서는 더 복잡한 초기화 로직을 구현할 수 있습니다.
  2. 유연성
    • 프로퍼티 선언 시 초기화: 단순한 값 할당에 적합하지만, 초기화 로직이 복잡하거나 조건이 필요할 때는 유연하지 않을 수 있습니다.
    • init에서 초기화: 초기화 시점에 더 복잡한 로직을 처리할 수 있으며, 다른 초기화 경로에 따라 다르게 설정할 수 있습니다.

어느 방식이 더 나을까?

  • 간단한 초기화(예: 기본 값 설정 또는 외부 호출 없이 초기화)에 적합한 경우에는 프로퍼티 선언 시 초기화가 더 간편하고 직관적입니다.
  • 초기화 과정에서 복잡한 로직이 필요하거나, 특정 순서를 요구하는 경우에는 init에서 초기화하는 방식이 더 적합합니다.

이 상황에서는 초기화 로직이 단순하다면, 프로퍼티 선언 시 초기화하는 방법이 더 간결하고 유용할 수 있습니다.

반응형