Difference between CurrentValueSubject and @Published

CurrentValueSubject is a value, a publisher and a subscriber all in one.

Sadly it doesn’t fire objectWillChange.send() when used inside an ObservableObject.

You can specify an error type.

@Published is a property wrapper, thus:

  • It is not yet supported in top-level code.
  • It is not supported in a protocol declaration.
  • It can only be used within a class.

@Published automatically fires objectWillChange.send() when used inside an ObservableObject.

Xcode will emit a warning if your try to publish to @Published wrapped property from a background queue. Probably because objectWillChange.send() must be called from the main thread.

The error type of its publisher is Never

My biggest beef against @Published is that it can’t behave as a subscriber and setting up Combine pipelines requires additional plumbing compared to a Current Value Subject.

We can declare a @Published property inside a protocol. Not very pretty...

protocol TestProtocol {
    var isEnabled: Bool { get }
    var isEnabledPublished: Published<Bool> { get }
    var isEnabledPublisher: Published<Bool>.Publisher { get }
}

class Test: ObservableObject, TestProtocol {
    @Published var isEnabled: Bool = false
    var isEnabledPublished: Published<Bool> { _isEnabled }
    var isEnabledPublisher: Published<Bool>.Publisher { $isEnabled }
}

@Published is just a quick way to use CurrentValueSubject a little neater. When I debug one of my apps and look at the type returned by $paramName , it's actually just a CurrentValueSubject:

po self.$books
▿ Publisher
  ▿ subject : <CurrentValueSubject<Array<Book>, Never>: 0x6000034b8910>

I guess one benefit of using CurrentValueSubject instead of @Published may be to allow you to use the error type?

Note: Despite being a CurrentValueSubject right now I'd never rely on that assumption.