Daltonicc/SwiftAndCSForMe

CurrentValueSubject vs @Published

Closed this issue · 0 comments

CurrentValueSubject vs @ Published Property Wrapper

  • Combine을 학습하다보면 @ Published라고 하는 프로퍼티래퍼와 CurrentValueSubject라는 개념이 존재한다. @ Published 프로퍼티 래퍼에 감싸진 변수와 CurrentValueSubject 둘다 초기값을 가지고 있고 구독 즉시 초기값을 방출한다는 공통된 특징을 가지고 있다.
    @Published var navigationTitleWithPublished: String = "Search"
    var navigationTitleWithSubject: CurrentValueSubject<String, Never> = .init("Search")

사실 둘다 공통된 특성을 가지고 있어서 특별히 커스텀 에러 처리를 해줄 필요가 없다면 뭘 사용할지는 취향이다. 다만 몇 가지 부분에 있어서 차이점이 존재한다.

@ Published

  • 프로퍼티 래퍼다보니 프로토콜에 선언해줄 수 없다.
protocol SearchViewModelOutput: AnyObject {
    func showErrorToast(errorMessage: String)
    
    @Published var error: String { get }   // "property 'error' declared inside a protocol cannot have a wrapper"
}
  • 마찬가지로 구조체에서도 사용할 수 없다.
struct PublishedTest {
    @Published var test: String = "Test" // " 'wrappedValue' is unavailable: @Published is only available on properties of classes"
}
  • CurrentValueSubejct와 달리 Combine을 import하지 않아도 사용할 수 있다.
  • 해당 프로퍼티 래퍼에 감싸진 변수를 사용할 때는 변수 앞에 기호 '$'를 붙여서 사용해야 한다.
$navigationTitleWithPublished
    .sink(receiveValue: { [weak self] title in
        self?.navigationItem.title = title
    })
    .store(in: &cancellables)
  • CurrentValueSubejct와 달리 현재 value를 가져오거나 새로운 값을 할당할 때, 따로 프로퍼티를 통하지 않고 바로 접근이 가능하다.
  • 마지막으로 이건 사소한거긴 한데, 프로퍼티 래퍼가 앞에 붙음으로써, 상대적으로 코드가 좀 더 깔끔해 보인다는 특징이 있다.

CurrentValueSubject

  • 위에서 기술해놓은 @ Published 프로퍼티 래퍼의 특징을 모두 반대로 가지고 있다.
  • 프로토콜에 선언해줄 수 있다.
  • 구조체에도 사용할 수 있다.
  • 반드시 Combine을 import해야 사용가능하다.
  • 사용할 때 따로 기호를 붙여줄 필요없다.
  • 현재 value를 가져올 때는 value 프로퍼티를 활용해야하고, 새로운 값을 할당할 때는 send메서드를 이용해야한다.
// 현재 value 가져오기
var testCurrnetValueSubject: CurrentValueSubject<String, Never> = .init("Test")
print(testCurrnetValueSubject.value) // "Test"

// 새로운 값 할당하기
testCurrnetValueSubject.send("Test2")
print(testCurrnetValueSubject.value) // "Test2"