Observing Changes in Multiple @Published Variables at the Same Time?

I have the following lines of code to subscribe text changes over two text fields.

import UIKit
import Combine

class ViewController: UIViewController {
	var cancellables = Set<AnyCancellable>()
	
	@Published var userText: String = ""
	@Published var passText: String = ""
	
	
	// MARK: - IBOutlet
	@IBOutlet var usernameTextField: UITextField!
	@IBOutlet var passwordTextField: UITextField!
	
	
	// MARK: - Life cycle
	override func viewDidLoad() {
		super.viewDidLoad()
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: usernameTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.userText = text
					}
				}
			})
			.store(in: &cancellables)
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: passwordTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.passText = text
					}
				}
			})
			.store(in: &cancellables)
		
		$userText
			.sink(receiveValue: { text in
				print(text)
			})
			.store(in: &cancellables)
	}
}

In the last several lines, I am printing the text change for userText. Does Combine allow me to observe two variables (userText, passText) at the same time so that I can plug them into a function? If yes, how?

Muchos Thankos.

Answered by Tomato in 693352022

I think I've figured it out for myself.

It looks like I can use Publishers.CombineLatest(,) as follows.

class ViewController: UIViewController {
	var cancellables = Set<AnyCancellable>()
	
	@Published var userText: String = ""
	@Published var passText: String = ""

	override func viewDidLoad() {
		super.viewDidLoad()
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: usernameTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.userText = text
					}
				}
			})
			.store(in: &cancellables)
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: passwordTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.passText = text
					}
				}
			})
			.store(in: &cancellables)

		Publishers.CombineLatest($userText, $passText)
			.sink { (result0, result1) in
				print(result0, result1)
			}.store(in: &cancellables)
	}
}
Accepted Answer

I think I've figured it out for myself.

It looks like I can use Publishers.CombineLatest(,) as follows.

class ViewController: UIViewController {
	var cancellables = Set<AnyCancellable>()
	
	@Published var userText: String = ""
	@Published var passText: String = ""

	override func viewDidLoad() {
		super.viewDidLoad()
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: usernameTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.userText = text
					}
				}
			})
			.store(in: &cancellables)
		
		NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: passwordTextField)
			.sink(receiveValue: { (result) in
				if let myField = result.object as? UITextField {
					if let text = myField.text {
						self.passText = text
					}
				}
			})
			.store(in: &cancellables)

		Publishers.CombineLatest($userText, $passText)
			.sink { (result0, result1) in
				print(result0, result1)
			}.store(in: &cancellables)
	}
}
Observing Changes in Multiple @Published Variables at the Same Time?
 
 
Q