작성
·
52
·
수정됨
0
import UIKit
class TestClass {}
class SomeClass {
var a = 10
var b = TestClass()
func myFunc() {
print(self.a)
}
lazy var myClosure1: (()->Void)? = {
() -> Void in
print(self.a)
}
lazy var myClosure2 = {
[a] () -> Void in
print(a)
}
lazy var myClosure3 = { [b] in
print(b)
}
deinit {
print("SomeClass deinit")
}
}
var myClass1: SomeClass? = SomeClass()
var myClass2 = myClass1
var myClass3 = myClass1
var myClass4 = myClass1
myClass1?.myClosure1
myClass1?.myClosure1 = nil
myClass1?.myClosure2
myClass1?.myClosure3
myClass1 = nil
myClass2 = nil
myClass3 = nil
myClass4 = nil
위 코드에서 myClusore3 의 캡쳐 리스트엔 b를 작성했고, b는 클래스의 인스턴스로 참조타입으로 알고 있습니다.
이 때 위 코드를 실행하면 deinit이 실행되는데요. weak 키워드를 사용하지 않았는데도 deinit이 실행되는 이유가 있을까요?
답변 2
0
안녕하세요
nil을 줘도 없어지지 않게 되려면 서로 강한참조 상태가 되는 즉 순환참조 상태로 만들어야 됩니다.
그러기 위해서는 SomeClass도 클로저를 강하게 참조하고 있어야 하고
클로저도 SomeClass를 강하게 참조하고 있어야 합니다.
SomeClass에 다음처럼 프로퍼티를 만들고
var c: TestClass?
매소드는 다음처럼 변경해 보세요
lazy var myClosure3 = { [b] in
print(b)
self.c = b
}
그리고 nil로 설정하기 전에 다음처럼 클로저를 실행시켜야 서로 강한참조를 하고 있는 상태가 되어 deinit이 호출 안되는걸 확인하실 수 있습니다.
myClass1?.myClosure3()
0
안녕하세요, 인프런 AI 인턴입니다. 왈티님.
질문해 주신 내용과 관련하여 “Swift에서의 클로저와 ARC”에 대해 설명드리겠습니다.
Swift의 클로저는 강하게 참조하는 클로저와 약하게 참조하는 클로저의 두 가지가 있습니다. 강한 참조는 클로저가 그 객체를 계속 참조하여 메모리에서 해제되지 못하게 만드는 경우입니다. 반대로 약한 참조는 객체가 해제될 수 있도록 돕습니다. weak
키워드를 사용하지 않고도 deinit
이 실행되는 이유를 이해하기 위해서는 강한 참조 사이클(Strong Reference Cycle)을 잘 이해해야 합니다.
클로저에서 캡쳐 리스트를 사용할 때, 클로저는 그 변수의 강한 참조를 유지하는 경우가 많습니다. 하지만 다음과 같은 경우, 강하게 참조하지 않아서 deinit이 호출될 수 있습니다.
lazy var myClosure3 = { [b] in
print(b)
}
위 코드에서 [b]
는 클로저가 b
를 캡쳐하지만 이 클로저는 SomeClass
의 인스턴스의 속성(myClosure3
)으로 잡혀 있습니다. 캡쳐된 b
는 클로저 내에서 사용되므로, b
에 대해 강한 참조가 일어나지 않습니다. 따라서, SomeClass
인스턴스의 모든 참조가 사라질 때 deinit
이 호출됩니다.
더 자세한 내용을 원하시면, 유사한 질문과 답변이 있는 다음 링크들을 추천해드립니다:
- 약한 참조를 할 경우 self에 ?를 붙여야 하는 이유?
- Closure에서의 개념 정리
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.