728x90
escaping closure의 의미
- 인자로 전달받은 closure 중 함수의 종료 이후에 실행될 수 있는 closure
- 저장, 지연될 수 있는 기능 블록을 가지는 closure가 바깥의 변수에 의해 저장되는 경우엔 escaping closure로 정의한다.
- 필요한 이유:
- 컴파일러의 최적화 때문
- non-escaping closure의 경우, closure가 언제 실행되고 종료되는지 알기 때문에, closure안의 객체들의 life cycle을 컴파일러가 관리하기가 용이하다. 그래서 optional로 필요한 경우에만 escaping을 명시적으로 사용할 수 있게 한다.
https://jusung.github.io/Escaping-Closure/
guard let strongSelf = self 사용 시 주의
- [weak self] 를 이용해서 클로져 내부에서 self를 weak 레퍼런스로 캡쳐하여도 guard let strongSelf = self 를 통해 강한 참조를 하는 순간 self의 reference count는 증가한다.
- 다만, weak self로 캡처를 하였으면 closure가 종료되면 count는 감소한다.
- weak self로 캡처를 하지 않고 closure내부에서 self를 강한 참조로 사용하면 closure가 종료되어도 count가 감소하지 않아서 self가 dealloc이 되지 않을 수도 있다.
- strongSelf 사용 시 적어도 클로저가 종료되기 전까지는 self가 메모리 해제되지 않음을 보장할 수 있다.
class Test {
lazy var closure: (() -> Void)? = { [weak self] in
print("weak \(CFGetRetainCount(self))") // weak 2
guard let strongSelf = self else { print("nil")
return }
print("strong \(CFGetRetainCount(strongSelf))") // strong 3 : 강한 참조로 인해 증가
strongSelf
}
}
var test: Test? = Test()
print("init \(CFGetRetainCount(test))")
test?.closure?()
print("after closure \(CFGetRetainCount(test))") // 클로저 종료되면서 strongSelf에 대한 참조 감소
/*
init 2
weak 2
strong 3
after closure 2
*/
closure내부에서의 weak self 사용
- escaping closure인 경우
- 무조건 weak self를 사용해야함
- escaping closure가 아닌 경우
- self가 closure보다 늦게 dealloc되는 경우 → weak self 사용할 필요 x
- self가 closure보다 일찍 dealloc되는 경우 -> closure에서 self를 참조하는 순간 크래시 발생 -> weak self 사용 필요
728x90
'Swift' 카테고리의 다른 글
[Swift] closure에서 self를 써야하는 이유 (0) | 2022.05.16 |
---|---|
[Swift] 캡처리스트 (Capture List) (0) | 2022.04.05 |
[Swift] allSatisfy(_:) (0) | 2022.03.28 |
[Swift] Extension에 storedProperty 선언하기 (0) | 2022.03.26 |
[Swift] Property Wrapper (0) | 2022.02.13 |
댓글