AnyCancellable
import Combine
import SwiftUI
struct CombineView: View {
var vm = CombineViewModel()
@State var anyCancellable = Set<AnyCancellable>()
@State var number = 0
var body: some View {
VStack {
Text("\(number)")
.padding()
Button(action: { vm.number.send(Int.random(in: 1...1000)) // # 수정됨
// print(vm.number)
}, label: {
Text("Button")
})
Button(action: {
anyCancellable.first?.cancel()
}) {
Text("Cancel")
}
.padding()
.onAppear {
vm.number.sink { [self] value in
DispatchQueue.main.async {
self.number = value
}
}.store(in: &anyCancellable)
}
}
}
}
class CombineViewModel {
var number = PassthroughSubject<Int, Never>()
}
Cancel을 누르는 순간 숫자가 변하지 않는 것을 볼 수 있을 것이다.
즉, AnyCancellable의 cancel 함수를 작동시키면 Publisher와 Subscriber의 관계를 끊는 것이다.
그럼 왜 끊는 것이 필요할까?
필요 없이 Subscriber를 작동하는 것은 큰 오버헤드를 가져오기 때문이다.
오버헤드(overhead): 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다.
자동으로 끊어 질까?
Publisher - Subscriber의 연결되어 있는 것은 큰 오버헤드가 발생한다.
코딩하다가 문뜩 생각이 들었다. 사실 Publisher-Subscriber는 사용자가 끊어주지 않으면 계속 연결되어 있는건가?
아니면 메모리에 사라지면 알아서 연결이 끊어지는 걸까?
오 다행히 마지막 줄을 보면 AnyCancellable은 메모리에서 해제될 때 자동으로 cancel을 호출한다고 적혀 있다.
그럼 화면이 사라짐과 동시에 메모리에서 해제됨으로 Publisher와 Subscriber의 관계를 끊어버리니 메모리와 오버헤드를 고려 안해도 될 것 같다!
하.지.만
다시 생각해보자. sink 함수의 반환 값은 AnyCancellable이다. 그리고 AnyCancellable은 Class 이다.
만약 값을 저장하지 않으면 생성과 동시에 메모리에서 사라진다.
즉 Publisher - Subscriber의 관계를 유지할 수 없다는 것이다.
그러니 Publisher - Subscriber의 관계를 유지 하고 싶다면 반드시 AnyCancellable을 변수에 저장하던가.
store 함수를 이용해 Set<AnyCancellable>
에 저장해야 할 것이다.
'Swift > Apple Framework' 카테고리의 다른 글
[iOS / SwiftUI] Paging 무한 스크롤 (0) | 2023.05.23 |
---|---|
[iOS / SwiftUI] Combine - URLSession (0) | 2023.05.08 |
[iOS / SwiftUI] Combine - CurrentValueSubject, PassthroughSubject (0) | 2023.05.02 |
[SwiftUI] StateObject와 ObservedObject 차이점 (0) | 2023.04.22 |
[iOS / Swift] sort() 는 어떤 알고리즘을 쓸까? (0) | 2023.04.22 |