emit upload state events when button is pressed, using combine in swift

We can use UIControl's addTarget(_:action:for:) method to listen to button press and then emit an upload state event. Here is a code snippet to achieve this:

main.swift
import UIKit
import Combine

class ViewController: UIViewController {

    private var uploadSubject = PassthroughSubject<Void, Never>()

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
        button.setTitle("Upload", for: .normal)
        button.addTarget(self, action: #selector(handleUpload), for: .touchUpInside)
        self.view.addSubview(button)

        let uploadStateSubscriber = uploadSubject
            .map { _ in true }
            .prepend(false)
            .eraseToAnyPublisher()
            .sink(receiveValue: { state in
                print("Upload Button State: \(state)")
            })

        // In this case we don't care about the reference of the subscription
        // as we only need to keep alive the subscription as long as the view controller is alive
        _ = uploadStateSubscriber
    }

    @objc private func handleUpload() {
        uploadSubject.send()
    }
}
1005 chars
33 lines

First, we create a PassthroughSubject<Void, Never> that will emit events when the button is pressed.

Next, we create a UIButton and add it to the view. We then listen to the touchUpInside control event using addTarget(_:action:for:) method and call the handleUpload function.

When the handleUpload function is called, we emit a value using the uploadSubject PassthroughSubject.

We then create a uploadStateSubscriber publisher that maps emitted values to a boolean where true means the button is in upload state and false means it's not. We also prepend false to the sequence so that the initial state of the button is not in upload state. Then, we print the button state whenever a new value is emitted.

Finally, we store the reference of the uploadStateSubscriber in a variable so that it stays alive as long as the ViewController is alive.

related categories

gistlibby LogSnag