@DevAndArtist, @Philippe_Hausler Please excuse my ignorance, but I am not only new to Combine but also to the whole reactive programming topic. And because Combine is also very new it is somewhat difficult to find any stuff related to this on the web. Also, even Apple's docs are merely bare bones.
So I still wonder if it is legal to connect more than one Subscriber to one Publisher or whether this Multicast feature is needed. In my experiment in the code above it seems to work without Multicast, but this could be a bug or quirk. I am asking because in some other code here: Crash in SwiftUI App using Combine (was: Using @Published in conjunction with @State in SwiftUI) - #5 by IOOI I have the problem, that some subsequent Publisher never fires. This Publisher, named validatedCredentials
is connected to two other publishers, validatedEMail
and validatedPassword
like this:
class RegistrationModel : BindableObject {
@Published var eMail: String = ""
@Published var password: String = ""
@Published var passwordRepeat: String = ""
public var didChange = PassthroughSubject<Void, Never>()
var validatedEMail: AnyPublisher<String?, Never> {
return $eMail
.debounce(for: 0.5, scheduler: RunLoop.main)
.removeDuplicates()
.flatMap { username in
return Future { promise in
self.usernameAvailable(username) { available in
promise(.success(available ? username : nil))
}
}
}
.eraseToAnyPublisher()
}
var validatedPassword: AnyPublisher<String?, Never> {
return Publishers.CombineLatest($password, $passwordRepeat)
.debounce(for: 0.5, scheduler: RunLoop.main)
.map { password, passwordRepeat in
guard password == passwordRepeat, password.count > 5 else { return nil }
return password
}
.eraseToAnyPublisher()
}
var validatedCredentials: AnyPublisher<(String, String)?, Never> {
return Publishers.CombineLatest(validatedEMail, validatedPassword)
.map { validatedEMail, validatedPassword in
guard let eMail = validatedEMail, let password = validatedPassword else { return nil }
return (eMail, password)
}
.eraseToAnyPublisher()
}
func usernameAvailable(_ username: String, completion: (Bool) -> Void) {
let isValidEMailAddress: Bool = NSPredicate(format:"SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}").evaluate(with: username)
completion(isValidEMailAddress)
}
}
Not shown here but maybe important: validatedEMail
and validatedPassword
are also connected to some SwiftUI Text-Views at the same time (just for debugging purposes).
So my question is: would I need some Multicast-Magic here to make it work? If so, how would I use this ConnectablePublisher
? Would I just add a .makeConnectable()
after the .eraseToAnyPublisher()
and change the method signature accordingly? What else would be needed?
Thanks a lot,
Lars