When calling Amplify.Auth.signUp(...).resultPublisher.sink, cannot reach receiveCompletion and receiveValue
here is my code
func signUp(username: String, password: String, email: String) -> AnyCancellable {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
let sink = Amplify.Auth.signUp(username: username, password: password, options: options)
.resultPublisher
.sink(receiveCompletion: {_ in
print("yeah!")
}, receiveValue: {_ in
print("yeah!!")
})
return sink
}
and when use func like this, it works
func signUpOld(username: String, password: String, email: String) {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
Amplify.Auth.signUp(username: username, password: password, options: options) { result in
switch result {
case .success(let signUpResult):
if case let .confirmUser(deliveryDetails, _) = signUpResult.nextStep {
print("Delivery details \(String(describing: deliveryDetails))")
} else {
print("SignUp Complete")
}
case .failure(let error):
print("An error occurred while registering a user \(error)")
}
}
}
hi @snowjujube,
thanks for reaching out.
Are you storing the returned Cancellable in a variable whose scope outlives the caller function scope (i.e. an instance variable) ?
Thank you for helping me to solve that problem, and I fix my code like this, and finally get the state in my console, but I'm confusing about why the code works now, hope if you can explain the principle, thanks again!
the code SwiftUI View
var cancellable = Set<AnyCancellable>()
struct ContentView: View {
@State var username = "xxxx"
@State var password = "xxxx"
@State var email = "xxxx"
func signUp(username: String, password: String, email: String) -> AnyCancellable {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
let sink = Amplify.Auth.signUp(username: username, password: password, options: options)
.resultPublisher
.sink {
if case let .failure(authError) = $0 {
print("An error occurred while registering a user \(authError)")
}
}
receiveValue: { signUpResult in
if case let .confirmUser(deliveryDetails, _) = signUpResult.nextStep {
print("Delivery details \(String(describing: deliveryDetails))")
} else {
print("SignUp Complete")
}
}
return sink
}
var body: some View {
VStack {
TextField("username", text: $username)
TextField("password", text: $password)
TextField("e-mail", text: $email)
Button("Sign Up", action: {
let result = signUp(username: username, password: password, email: email)
result.store(in: &cancellable)
})
}
}
}
and without these two lines, my console didn't work anymore:
var cancellable = Set<AnyCancellable>()
result.store(in: &cancellable)
I've try some other publishers without cancel or store, and they work.
@diegocstn thanks!鉂わ笍
It's related to how Combine handles cancellables lifecycle :)
Most helpful comment
It's related to how Combine handles cancellables lifecycle :)