Swift) lazy와 weak를 같이 쓸 수 없는 이유

결론부터 말하자면 lazy와 weak를 동시에 사용할 경우 객체가 즉시 해제되어서 정상적으로 작동할 수 없으므로 컴파일 오류가 뜬다.

 

lazy 프로퍼티

lazy 프로퍼티는 처음 객체가 생성될때 초기화 되는 것이 아닌 해당 프로퍼티가 사용될 때 초기화 되는 프로퍼티

 

weak

해당 프로퍼티가 약한 참조로 Reference Counter를 올리지 않게 되며, 해당 객체가 런타임 도중 할당이 해제되면 해당 프로퍼티는 nil값으로 변경된다.

 

lazy 와 weak를 같이 쓴다면

class B {
    var hello = "Hello"
}

class A {
    lazy weak var b: B? = B()
    
    func asd() {
        print(b!.hello)
    }
}

let a = A()

이런 코드가 있다고 해보자. 

여기서 A 객체를 생성하면 b는 lazy 이므로 아직 생성이 안 된 상태일 것이다.

 

그 후 a의 b에 접근해 hello를 출력하려고 하면 이때 b가 초기화되면서 다음과 같은 상태가 될 것이다.

print(a.b?.hello)

하지만 초기화가 되었지만 weak 이기에 Reference Count가 증가하지 않으므로 0이 되면서 ARC에 의해 메모리에서 해제. A의 프로퍼티인 b는 nil이 되어버린다.

따라서 b는 nil값이므로 b의 코드는 실행되지 않는다.

외부에서 객체를 주입하는 경우

class B {
    var hello = "Hello"
    
    init(hello: String) {
        self.hello = hello
    }
    
    func hi() {
        print("Nice to meet you")
    }
}

class A {
    lazy weak var b: B? = B(hello: "Hello")
    
    func asd() {
        print(b!.hello)
    }
}

let a = A()
let subB = B(hello: "Hi")
a.b = subB

이런식으로 외부에서 객체를 주입하는 경우에는 A의 파라미터인 b가 할당 해제되지 않고 사용 할 수 있다. 그러나 이 경우에는 그냥 weak를 사용할때와 다를게 없다. 

 

 그래서 lazy와 weak를 같이 사용하면 바로 컴파일 오류가 뜨도록 해둔 듯하다.