1

I want to listen to changes to $email and $password, and then store the result in signInDisabled, but I'm not sure how to listen to changes from both.

@Published var email = ""
@Published var password = ""
var signInDisabled = true

var session : SessionListenerProtocol
private var cancellables = Set<AnyCancellable>()


init(){
    
// ???
    $email, $password  { email, password in
        email == "" || password == ""
    }
    .assign(to: \.signInDisabled, on: self)
    .store(in: &cancellables)

}
Spdollaz
  • 165
  • 10
  • Depends what you mean. You could use merge, zip, or combineLatest. See my https://stackoverflow.com/a/67099668/341994 for some discussion, and online book for details. https://www.apeth.com/UnderstandingCombine/operators/operatorsJoiners/operatorsjoiners.html – matt May 15 '21 at 21:37
  • @matt I tried $email.zip($password) { email, password But the function was only triggered when email was modified, not password. – Spdollaz May 15 '21 at 21:45

1 Answers1

1

I assume that you are using iOS14 as a minimum target. When using .assign(to:on:) and adding self to it, it will create memory leak. There is an update to iOS 14 where you would use .assign(to: &) instead. You also don't need .store(in: &cancellables) when using .assign(to:).

To have the behavior you are looking for, I suggest you to use the .combineLatest tool that will read both of your values and don't forget to make signInDisabled a @Publisher to be read as a Combine value. I also added a .removeDuplicates() to avoid the Combine pipeline to set several times the same value to signInDisabled when not needed.

@Published var email = String()
@Published var password = String()
@Published var signInDisabled = true

init(){
  $email
    .combineLatest($password)
    .map { $0.0 == String() || $0.1 == String() }
    .removeDuplicates()
    .assign(to: &$signInDisabled)
} 
Roland Lariotte
  • 2,606
  • 1
  • 16
  • 40