I'd like to trigger a "change" event on every change of either the username
or password
published properties and set a new Credentials
published property derived of those two and emit an event.
What would be the simplest solution to achieve this result using SwiftUI & Combine?
Some sample code with the idea I'm trying to achieve:
import SwiftUI
import Combine
import Foundation
struct Credentials {
let username: String
let password: String
init(username: String = "",
password: String = "") {
self.userName = username
self.password = password
}
}
final class ViewModel: ObservableObject {
@Published var username = ""
@Published var password = ""
@Published var credentials = Credentials()
init() {
[$username, $password]// ..... What to do here?
// How to "subscribe" each of those properties to emit an event
// so that I get notified each time one of them changes
credentials = Credentials(username: $username, password: $password)
}
}
Essentially, I'm looking to something similar to this answer: Swift Combine: How to create a single publisher from a list of publishers?
But with the notification should be triggered each time any of the publishers produce a value, not all of them.
Instead of using Publishers.MergeMany
as in your linked question, you want to use .combineLatest(_:)
on your first publisher, like so:
import SwiftUI
import Combine
import Foundation
struct Credentials {
let username: String
let password: String
init(username: String = "",
password: String = "") {
self.userName = username
self.password = password
}
}
final class ViewModel: ObservableObject {
@Published var username = ""
@Published var password = ""
@Published var credentials = Credentials()
private var cancellable: Cancellable? = nil
init() {
cancellable = $username.combineLatest($password).sink { tuple in
self.credentials = Credentials(username: tuple.0, password: tuple.1)
}
credentials = Credentials(username: username, password: password)
}
}
(it's been a bit so this code may not run immediately, but hopefully you see where this is going).