Search code examples
iosswiftcombine

Apple Combine add TapPublisher to UIView


Can I add a tap publisher to a UIView or UILabel? UIButton has tapPublisher built in. I tried making an extension, but extensions can't store properties.

Also, is it bad practices to try and use a tap publisher on anything that isn't a button?

    func bindViewModel() {
        cancellables = [
            continueButton.tapPublisher.sink { [unowned self] in
                viewModel.action
                    .send(.question)
            },
            headlineLabel.tapPublisher.sink {
                // Error: "Value of type 'UILabel' has no member 'tapPublisher'..."
            })
        ]
    }

Solution

  • Actually UIButton doesn't have it built in. I suggest you're using extension from Building custom Combine publishers in Swift

    For the button it's pretty clear, inside you just subscribe to .touchUpInside action.

    But with UILabel or UIView it's not that clear: you have to add your gesture recogniser, make sure that you won't add one more if you've already added it.

    You can check gestureRecognizers, but there's still a chance that it's not yours gestureRecognizer you're trying to subscribe to. You can store yours in an associated object, but this not the best solution in terms of performance.

    For UILabel you also need to turn on userInteractionEnabled.

    I'd say it's too much logic for an extension, but it's up to you.