When you use the .sink
operator, it returns a token of type AnyCancellable
. When that token is destroyed, it calls cancel
on itself, which tears down the subscription it represents. You're not saving the token, so Swift destroys it immediately, before the subscription has had a chance to deliver any outputs.
The usual solution is to find a place to store the token, like in a property of a controller object:
class AccountCreationController: UIViewController {
private var token: AnyCancellable? = nil
// NEW ^^^^^ storage for the AnyCancellable
@objc private func createAccountButtonAction(sender: UIButton) {
print("Create Account Button Action")
signUp(password: self.password, email: self.email)
}
func signUp(password: String, email: String) {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
token = Amplify.Auth.signUp(username: email, password: password, options: options)
// NEW ^^^^^ store the AnyCancellable to keep the subscription alive
.resultPublisher.sink(
receiveCompletion: { (authError) in
print("Failed with error: (authError)")
},
receiveValue: { (signUpResult) in
print("Signed Up")
})
}
}
An alternative, if you are sure you never want to cancel the subscription (e.g. the user cannot press a “Cancel”?button to back out), is to create a Subscribers.Sink
directly, instead of using the sink
operator, and use the subscribe
method to subscribe the Sink
to the Publisher
. The subscribe
method does not return an AnyCancellable
. The Sink
object is itself a Cancellable
, but not an AnyCancellable
, and you don't have to store it anywhere to keep the subscription alive.
class AccountCreationController: UIViewController {
@objc private func createAccountButtonAction(sender: UIButton) {
print("Create Account Button Action")
signUp(password: self.password, email: self.email)
}
func signUp(password: String, email: String) {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
Amplify.Auth.signUp(username: email, password: password, options: options)
// NEW ^ There is no AnyCancellable to store.
.resultPublisher
.subscribe(
// NEW ^^^^^^^^^^ use the subscribe method instead of sink.
Subscribers.Sink(
// NEW ^^^^^^^^^^^^^^^^ Create a Sink object.
receiveCompletion: { (authError) in
print("Failed with error: (authError)")
},
receiveValue: { (signUpResult) in
print("Signed Up")
}
)
)
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…