Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active May 2, 2021 17:38
Show Gist options
  • Save fxm90/a32c8db5a2b29f1426369370d335c128 to your computer and use it in GitHub Desktop.
Save fxm90/a32c8db5a2b29f1426369370d335c128 to your computer and use it in GitHub Desktop.
Gist showing the difference between the property wrapper `@Published` and a `CurrentValueSubject`
//
// CombinePublishedVsCurrentValueSubject.playground
//
// Created by Felix Mau on 09.02.21.
// Copyright © 2021 Felix Mau. All rights reserved.
//
import Foundation
import Combine
class PublishedTest {
/// > When the property changes, publishing occurs in the property’s `willSet` block,
/// > meaning subscribers receive the new value before it’s actually set on the property.
/// https://developer.apple.com/documentation/combine/published
@Published
var numberOfAdults: Int = 0
}
class SubjectTest {
var numberOfAdults: Int {
get { numberOfAdultsSubject.value }
set { numberOfAdultsSubject.value = newValue }
}
var numberOfAdultsPublisher: AnyPublisher<Int, Never> {
numberOfAdultsSubject.eraseToAnyPublisher()
}
private let numberOfAdultsSubject = CurrentValueSubject<Int, Never>(0)
}
var subscriptions = Set<AnyCancellable>()
// MARK: - `@Published` Test
let publishedTest = PublishedTest()
publishedTest.$numberOfAdults.sink { [weak publishedTest] in
print("@Published: Value passed to closure", $0)
print("@Published: Value on class property", publishedTest!.numberOfAdults) // <- As `@Published` uses `willSet` the value is not updated here.
}.store(in: &subscriptions)
publishedTest.numberOfAdults = 1
publishedTest.numberOfAdults = 2
// Output
//
// @Published: Value passed to closure 0
// @Published: Value on class property 0
// @Published: Value passed to closure 1 ‼️
// @Published: Value on class property 0 ‼️
// @Published: Value passed to closure 2 ‼️
// @Published: Value on class property 1 ‼️
//
// -> Closure gets informed with initial value, therefore it seems like `@Published` uses a `CurrentValueSubject` internally.
// MARK: - `CurrentValueSubject` Test
let subjectTest = SubjectTest()
subjectTest.numberOfAdultsPublisher.sink { [weak subjectTest] in
print("CurrentValueSubject: Value passed to closure", $0)
print("CurrentValueSubject: Value on class property", subjectTest!.numberOfAdults)
}.store(in: &subscriptions)
subjectTest.numberOfAdults = 1
subjectTest.numberOfAdults = 2
// Output
//
// CurrentValueSubject: Value passed to closure 0
// CurrentValueSubject: Value on class property 0
// CurrentValueSubject: Value passed to closure 1
// CurrentValueSubject: Value on class property 1
// CurrentValueSubject: Value passed to closure 2
// CurrentValueSubject: Value on class property 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment