arsena
arsena

Reputation: 1975

What is the correct way of using void @Published variables in combine?

Lets assume I have a ViewControllerA that presents ViewControllerB and I want to subscribe to a button tap. I can do something like this:

public class ViewControllerB {
    public var didTapButton = PassthroughSubject<Void, Never>()
    ...

    func buttonTapped() {
        didTapButton.send(completion: .finished)
    }
}

then subscribe to didTapButton in ViewControllerA with sink.

If I want to do the same with @Published variable, all I can think of is doing this:

public class ViewControllerB {
    @Published public var didTapButton: Void?
    ...

    func buttonTapped() {
        didTapButton = ()
    }
}

Does this make sense? or is there better way to do this?

Upvotes: 3

Views: 1310

Answers (1)

matt
matt

Reputation: 535944

In the code you've shown, public var didTapButton is not @Published. So the question as it stands doesn't make much sense.

If you wanted to make it @Published I would recommend typing it as Bool. Then you just ignore the actual Bool value; it is the signal itself you are after. You would just toggle() the Bool to make the @Published variable emit a signal. Working with Void signals, as I think you've noticed, is not all that pleasant in Combine.

However, I happen to think that a passthrough subject is a much nicer (and far more powerful and flexible) approach, and I don't see why you would reject using it.

Another thing to note is that the use of the IBAction as an intermediary is somewhat clunky. You can add a UIControl publisher so that you can subscribe directly to the button tap. What I do in my own apps where there is this kind of relaying is to .subscribe the passthrough subject to the UIControl publisher. The ability to do that is part of what makes a Subject so wonderful: it can itself be a publisher or an operator in the middle of the chain, so it can be used to relay the signal from one view controller to another automatically — there is no need to say send to it. Observe that what I send via the passthrough subject in that example is neither a Bool nor a Void nor a completion, but rather a custom enum that tells the recipient exactly what just happened (in terms of intent).

Upvotes: 2

Related Questions