Practical Use of Combine's Subject

I'm trying to understand how Combine works. The following is my sample code.

import UIKit
import Combine

class ViewController: UIViewController {
	// MARK: - Variables
	var cancellable: AnyCancellable?
	
	
	// MARK: - IBAction
	@IBAction func buttonTapped(_ sender: UIButton) {
		currentValueSubject.send(20)
	}
	
	
	// MARK: - Life cycle
	var currentValueSubject = CurrentValueSubject<Int, Never>(1)
	override func viewDidLoad() {
		super.viewDidLoad()
		
		let cancellable = currentValueSubject
			.sink { value in
				print("New value: \(value)")
		}
		currentValueSubject.send(5)
		currentValueSubject.send(10)
		//currentValueSubject.send(completion: .finished)
		currentValueSubject.send(15)
		//cancellable.cancel()
	}
}

If I run it with the iPhone simulator, I get

New value: 1

New value: 5

New value: 10

New value: 15

If I tap the button, the app won't get a new value. I suppose that's because the subscription is cancelled at the end of viewDidLoad? If so, why does it get cancelled? I don't quite see a practical side of Combine's Subject. When is it useful? Thanks.

Answered by OOPer in 686267022

In your viewDidLoad() you declare a local variable cancellable, which is disposed at the end of the scope. In your case, it is at the end of viewDidLoad.

Please try something like this:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.cancellable = currentValueSubject
        .sink { value in
                print("New value: \(value)")
        }
        currentValueSubject.send(5)
        currentValueSubject.send(10)
        //currentValueSubject.send(completion: .finished)
        currentValueSubject.send(15)
        //cancellable.cancel()
    }
Accepted Answer

In your viewDidLoad() you declare a local variable cancellable, which is disposed at the end of the scope. In your case, it is at the end of viewDidLoad.

Please try something like this:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.cancellable = currentValueSubject
        .sink { value in
                print("New value: \(value)")
        }
        currentValueSubject.send(5)
        currentValueSubject.send(10)
        //currentValueSubject.send(completion: .finished)
        currentValueSubject.send(15)
        //cancellable.cancel()
    }

Oh, I see. Silly me... Thanks a lot.

Practical Use of Combine's Subject
 
 
Q