Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- map
- ios
- ribs
- SWIFT
- uiscrollview
- 리펙토링
- MVVM
- 리팩토링
- collectionview
- 리펙터링
- swift documentation
- clean architecture
- swiftUI
- 애니메이션
- UITextView
- 스위프트
- Observable
- uitableview
- RxCocoa
- rxswift
- 클린 코드
- Clean Code
- Refactoring
- combine
- Protocol
- Human interface guide
- UICollectionView
- Xcode
- tableView
- HIG
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 3. 클로저를 사용할 때 주의할 점 - nested closure 세 번째 본문
1. 클로저를 사용할 때 주의할 점 - Memory Leaks, Retain Cycle, nested closure 첫 번째
2. 클로저를 사용할 때 주의할 점 - nested closure 두 번째
3. 클로저를 사용할 때 주의할 점 - nested closure 세 번째
nested closure에서 weak로 잡지 않는 경우
- closure가 두 번 생길 때 아래와 같은 경우가 존재
- ss.instance?.f1 클로저 안에 ss.instance?.f2가 있고, 모두 RxSwift에서 제공하는 연산자 subscribe(with: self)로 접근함으로써 self는 weak로 잡은 상태
weak var instance: SomeClass?
button.rx.tap
.subscribe(with: self) { ss, _ in
ss.instance?.f1 {
print("ss1")
ss.instance?.f2 {
print("ss2")
}
}
}
.disposed(by: disposeBag)
- 이때 ss를 접근할 때 f1 클로저에서도 weak를 쓰지 않았는데 메모리릭이 발생할 것인지?
- 정답) f1 클로저를 ss.instance에서 전역변수에 저장해놓지 않으면 메모리릭이 발생하지 않고, 저장해놓으면 메모리릭이 발생함
nested closure에서 메모리가 발생하는 상황
- 2번째 nested closure에서 전역에 값을 저장하는 경우
weak var instance: SomeClass?
button.rx.tap
.subscribe(with: self) { ss, _ in
ss.instance?.f1 {
print("ss1")
ss.instance?.f2 {
print("ss2")
}
}
}
.disposed(by: disposeBag)
class SomeClass {
var closure1: (() -> ())?
func f1(_ closure: @escaping () -> ()) {
print("f1")
closure1 = closure
closure()
}
func f2(_ closure: @escaping () -> ()) {
print("f2")
}
}
- 이유)
- 클로저를 사용할 때 주의할 점 - nested closure 두 번째 글에서 알아 보았듯이 [weak self] 캡쳐리스트 뜻은 self가 가리키는 대상을 weak로 참조한다는 뜻이고 다시 내부 클로저에서 사용할 경우 weak self가 참조하는 대상을 strong하게 접근한다는 의미
- 즉, f1클로저 내부에서 ss가 가리키는 값을 strong으로 참조하고 있는데, 이 때 f1 내부에서 클로저를 전역에 저장해놓으면서 순환참조가 발생하는 것
ss --> f2
ss <-- f2
- ss를 다시 weak로 접근해야 메모리릭이 나지 않음
button.rx.tap
.subscribe(with: self) { ss, _ in
ss.instance?.f1 { [weak ss] in // <-
print("ss1")
ss?.instance?.f2 {
print("ss2")
}
}
}
.disposed(by: disposeBag)
- 또는 f1클로저에서 클로저 내용을 전역에 저장하는 부분을 삭제해도 메모리릭이 나지 않음
class SomeClass {
var closure1: (() -> ())?
func f1(_ closure: @escaping () -> ()) {
print("f1")
// closure1 = closure <- 주석처리하면 메모리릭이 발생하지 않음
closure()
}
func f2(_ closure: @escaping () -> ()) {
print("f2")
}
}
* 전체 코드: https://github.com/JK0369/ExMemoryLeakInNestedClosure
'iOS 응용 (swift)' 카테고리의 다른 글
Comments