-
Combine - 연산자 receive/sink/storeSwift 2024. 2. 21. 21:49
viewModel.selectedItem .compactMap { $0 } .receive(on: RunLoop.main) .sink { framework in let sb = UIStoryboard(name: "Detail", bundle: nil) let vc = sb.instantiateViewController(withIdentifier: "FrameworkDetailViewController") as! FrameworkDetailViewController vc.viewModel = FrameworkDetailViewModel(framework: framework) self.present(vc, animated: true) }.store(in: &subscriptions)
해당 코드는 Combine 프레임워크를 사용하여 데이터 흐름을 처리하는 방식을 보여주는 예시입니다. 코드를 각 부분별로 설명하겠습니다:
1. `viewModel.selectedItem`: `viewModel` 객체의 `selectedItem` 속성을 나타냅니다. 이 속성은 Combine의 `CurrentValueSubject`나 `PassthroughSubject`와 같은 Publisher 타입입니다.
2. `.compactMap { $0 }`: `selectedItem`의 값을 optional에서 non-optional로 변환하기 위해 `compactMap` 연산자를 사용합니다. optional 값을 unwrapping하고, non-optional 값만을 포함하는 스트림을 생성합니다.
3. `.receive(on: RunLoop.main)`: 데이터 스트림을 메인 스레드에서 처리하도록 지정합니다. UI 업데이트와 관련된 작업은 일반적으로 메인 스레드에서 수행되어야 하므로, `receive(on:)` 연산자를 사용하여 메인 스레드에서 처리하도록 설정합니다.
4. `.sink { framework in ... }`: 데이터 스트림의 값을 받아 처리하는 부분입니다. `sink` 연산자를 사용하여 데이터 스트림의 값을 받아옵니다. 클로저에서는 받아온 `framework` 값을 사용하여 `FrameworkDetailViewModel`을 생성하고, 해당 뷰 모델을 이용하여 `FrameworkDetailViewController`를 생성하고 표시합니다.⭐️실제로 데이터를 처리하는 부분
위 코드에서는 viewController를 생성(FrameworkDetailViewModel)하고, 데이터를 넣어준다.
5. `.store(in: &subscriptions)`: `sink` 연산자에서 반환된 `AnyCancellable`을 `subscriptions` 변수에 저장합니다. `AnyCancellable`은 데이터 스트림의 구독을 취소할 수 있는 기능을 제공합니다. 해당 구독을 취소하려면 `subscriptions` 변수에 저장된 `AnyCancellable` 객체를 해제해야 합니다.
.store(in: &subscriptions)부분이 없으면?
이 코드는 Combine을 사용하여 데이터 흐름을 처리하고, `selectedItem`의 값이 변경되면 해당 값을 처리하는 방식을 보여줍니다. `selectedItem`의 값이 변경되면 메인 스레드에서 `FrameworkDetailViewController`를 생성하고 표시하는 동작이 수행됩니다..store(in: &subscriptions) 부분이 없다면, 구독이 AnyCancellable 객체에 저장되지 않고 따로 참조되지 않게 됩니다.
이 경우, 구독이 유지되는 동안 AnyCancellable 객체가 존재하지 않기 때문에 구독을 취소하거나 해제할 수 있는 참조가 없게 됩니다. 따라서, 해당 구독을 취소하거나 해제할 수 있는 방법이 제한되며, 메모리 누수가 발생할 수 있습니다.
따라서, AnyCancellable 객체를 적절히 저장하는 것은 구독의 수명 주기를 관리하고 메모리 누수를 방지하기 위해 중요합니다. .store(in: &subscriptions)를 통해 AnyCancellable 객체를 subscriptions 변수에 저장함으로써, 필요한 시점에 구독을 취소하고 메모리를 해제할 수 있게 됩니다..store(in: &subscriptions) 외에도 구독을 관리하고 해제하는 다른 방법들이 있습니다.
- 수동으로 구독 취소: AnyCancellable 객체를 직접 해제하는 방법입니다. 구독을 취소하기 위해 cancel() 메서드를 호출하면 됩니다. 예를 들어, 구독을 취소하고 AnyCancellable 객체를 해제하려면 다음과 같이 할 수 있습니다:
let cancellable = somePublisher.sink { value in // 처리 로직 } // 구독 취소 cancellable.cancel()
Assign 연산자 사용: @Published 속성이나 ObservableObject를 사용하는 경우, assign(to:on:) 메서드를 사용하여 구독을 생성하고 속성에 값을 할당할 수 있습니다. 이 경우, AnyCancellable 객체를 따로 저장할 필요가 없습니다. 예를 들어:
class MyViewModel: ObservableObject { @Published var someValue: Int = 0 private var cancellable: AnyCancellable? init() { cancellable = somePublisher.assign(to: \.someValue, on: self) } }
위의 코드에서 assign(to:on:) 메서드를 사용하여 somePublisher의 값을 someValue에 할당하고, 구독을 생성합니다. cancellable 변수는 AnyCancellable 타입으로 선언되었지만, assign(to:on:) 메서드에 의해 자동으로 해제됨.
'Swift' 카테고리의 다른 글
MVVM / MVC (0) 2024.02.21 UIkit과 SwiftUI이용하여 Scroll Paging 구현하기 (0) 2024.01.27 [Swift] Firebase - FireStore 등록 addDocument (0) 2024.01.07 애플 ABM(Apple Business Manager) 등록 기록, 애플 회사 기기 등록 (1) 2023.12.22 lazy 코드 : 지연 초기화, 해당 프로퍼티 사용될 때 까지 초기화 되지 않음. (0) 2023.12.21 - 수동으로 구독 취소: AnyCancellable 객체를 직접 해제하는 방법입니다. 구독을 취소하기 위해 cancel() 메서드를 호출하면 됩니다. 예를 들어, 구독을 취소하고 AnyCancellable 객체를 해제하려면 다음과 같이 할 수 있습니다: