【问题标题】:Combine .sink print doesn't print结合 .sink 打印不打印
【发布时间】:2021-01-12 20:51:47
【问题描述】:

我是 Combine 和 Sink 的新手,但是我放入其中的打印似乎没有记录,但是操作的结果在 AWS Amplify 中创建用户时完成。

@objc private func createAccountButtonAction(sender: UIButton) {
    print("Create Account Button Action")
    signUp(password: self.password, email: self.email)
  }
  
  func signUp(password: String, email: String) -> AnyCancellable {
      let userAttributes = [AuthUserAttribute(.email, value: email)]
      let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
      let sink = Amplify.Auth.signUp(username: email, password: password, options: options)
        .resultPublisher.sink(receiveCompletion: { (authError) in
          print("Failed with error: \(authError)")
        }, receiveValue: { (signUpResult) in
          print("Signed Up")
        })
    return sink
  }

【问题讨论】:

  • 不,我不明白。您返回一个名为 sink 的组合管道,但您从不使用它做任何事情。你的意思是store它在某个地方吗?如果你不这样做,你的组合管道永远不会运行;它会立即死亡。
  • @matt,哦,这解释了为什么我看不到打印结果,但是我只遵循 AWS Amplify 教程,它不知道如何使用这些功能 :( 但是谢谢你,我会去探索水槽和商店
  • 我对 Amplify 对 Combine 的支持一无所知。我只是在评论返回管道然后将其丢弃的不连贯性。有关一些实际工作示例,请参阅我的 apeth.com/UnderstandingCombine/start/startpipelines.html
  • 现在遇到同样的问题!这些帖子很有帮助。 Amplify 文档通常很棒,但似乎暗示了对 Combine 框架的先验知识。谢谢大家。

标签: swift aws-amplify combine


【解决方案1】:

当您使用.sink 运算符时,它会返回AnyCancellable 类型的令牌。当该令牌被销毁时,它会在自身上调用cancel,这会破坏它所代表的订阅。您没有保存令牌,因此 Swift 会在订阅有机会提供任何输出之前立即销毁它。

通常的解决方案是找到一个存储令牌的地方,比如在控制器对象的属性中:

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")
                })
    }
}

如果您确定不想取消订阅(例如,用户无法按“取消”按钮退出),另一种方法是直接创建 Subscribers.Sink,而不是使用 sink 运算符,并使用subscribe 方法将Sink 订阅到Publishersubscribe 方法确实返回AnyCancellableSink 对象本身是 Cancellable,但不是 AnyCancellable,您不必将其存储在任何地方以保持订阅有效。

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")
                    }
                )
            )
    }
}

【讨论】:

  • 非常感谢,您的解释很有道理,而且帮助很大!
猜你喜欢
  • 2021-06-30
  • 2019-03-11
  • 2017-07-17
  • 2010-10-21
  • 2019-01-07
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
相关资源
最近更新 更多