无法转换“AuthResultCallback”类型的值?

Posted

技术标签:

【中文标题】无法转换“AuthResultCallback”类型的值?【英文标题】:Cannot convert value of type `AuthResultCallback`? 【发布时间】:2020-06-06 11:44:49 【问题描述】:

我知道其他类似的问题,但它们分别与 Auth.auth().signInsignUp 有关,其中函数中存在完成处理程序参数。

我试图在我的 SessionStore 类的匿名函数中包含一个登录,以便我的应用程序观察用户的状态,即他是否登录(匿名或其他方式)或退出,并相应地显示相关视图。

但是,当尝试将匿名注册添加到我的 SessionStore 课程时,我收到以下错误:

Cannot convert value of type 'AuthResultCallback' (aka '(Optional<User>, Optional<Error>) -> ()') to expected argument type 'AuthDataResultCallback?' (aka 'Optional<(Optional<AuthDataResult>, Optional<Error>) -> ()>')

我的代码如下:

class SessionStore: ObservableObject 
    var didChange = PassthroughSubject<SessionStore, Never>()

    @Published var session: User? didSet self.didChange.send(self)
    var handle: AuthStateDidChangeListenerHandle?

     func listen() 
         handle = Auth.auth().addStateDidChangeListener( (auth, user) in
            if let user = user 
                self.session = User(uid: user.uid, email: user.email)
             else 
                self.session = nil
            
        )
    

    func signUp(email: String, password: String, handler: @escaping AuthDataResultCallback) 
        Auth.auth().createUser(withEmail: email, password: password, completion: handler)
    

    func signIn(email: String, password: String, handler: @escaping AuthDataResultCallback) 
        Auth.auth().signIn(withEmail: email, password: password, completion: handler)
    

    func signOut() 
        do 
            try Auth.auth().signOut()
            self.session = nil
         catch 
            print("Error signing user out")
        
    

    func signUpAnonymously(handler: @escaping AuthResultCallback) 

        Auth.auth().signInAnonymously(completion: handler) // **ERROR APPEARS HERE**

    

    func unbind() 
        if let handle = handle 
            Auth.auth().removeStateDidChangeListener(handle)
        
    

    deinit 
        unbind()
    



struct User 

    var uid: String
    var email: String?

    init(uid: String, email: String?) 
        self.uid = uid
        self.email = email
    

谁能告诉我如何解决这个错误?

【问题讨论】:

两个完成处理程序不同 typealias AuthDataResultCallback = (FIRAuthDataResult?, Error?) -&gt; Void signInAnonymously(completion:) 的声明是什么?它似乎想要一个AuthDataResultCallback 参数,而你给它一个AuthResultCallback 一个。那是正常的,有不匹配的。 typealias AuthResultCallback = (FIRUser?, Error?) -&gt; Void 请注意,函数 func signUpAnonymously(handler: 没有从代码中的其他任何地方调用,因此我们不知道它是如何使用的或传入了什么。而且,@Larme 提到,这个@escaping AuthResultCallback 不匹配,因为 .signInAnonymously 期待 AuthDataResultCallback 【参考方案1】:

您粘贴的代码 sn-p 来自过时的教程。从 Xcode 11 beta 5 开始,您不再需要使用 PassthroughSubject 来发送有关属性更改的通知。 Sarun's blog post 有一个很棒而简洁的部分介绍了哪些变化,我鼓励你阅读它。

还请注意,如果您只关心用户的 ID 和他们的电子邮件地址,则不需要定义自己的 User 类,因为这些属性已经在 Firebase 自己的 User 类型中定义(通过实现UserInfo 协议)。

这是一个 sn-p,它展示了如何实现您感兴趣的回调(请参阅registerStateListener)。

class AuthenticationService: ObservableObject 

  @Published var user: User?

  private var handle: AuthStateDidChangeListenerHandle?

  init() 
    registerStateListener()
  

  func signIn() 
    if Auth.auth().currentUser == nil 
      Auth.auth().signInAnonymously()
    
  

  func signOut() 
    do 
      try Auth.auth().signOut()
    
    catch 
      print("Error when trying to sign out: \(error.localizedDescription)")
    
  

  func updateDisplayName(displayName: String, completionHandler: @escaping (Result<User, Error>) -> Void) 
    if let user = Auth.auth().currentUser 
      let changeRequest = user.createProfileChangeRequest()
      changeRequest.displayName = displayName
      changeRequest.commitChanges  error in
        if let error = error 
          completionHandler(.failure(error))
        
        else 
          if let updatedUser = Auth.auth().currentUser 
            print("Successfully updated display name for user [\(user.uid)] to [\(updatedUser.displayName ?? "(empty)")]")
            // force update the local user to trigger the publisher
            self.user = updatedUser
            completionHandler(.success(updatedUser))
          
        
      
    
  

  private func registerStateListener() 
    if let handle = handle 
      Auth.auth().removeStateDidChangeListener(handle)
    
    self.handle = Auth.auth().addStateDidChangeListener  (auth, user) in
      print("Sign in state has changed.")
      self.user = user

      if let user = user 
        let anonymous = user.isAnonymous ? "anonymously " : ""
        print("User signed in \(anonymous)with user ID \(user.uid). Email: \(user.email ?? "(empty)"), display name: [\(user.displayName ?? "(empty)")]")
      
      else 
        print("User signed out.")
        self.signIn()
      
    
  


如果您对更多背景感兴趣,请查看我关于使用 SwiftUI 和 Firebase 构建待办事项应用程序的系列文章:part 1(使用 SwiftUI 构建 UI)、part 2(在 Firestore 中存储数据并使用Firebase 匿名身份验证),part 3(使用 Apple 登录)

【讨论】:

以上是关于无法转换“AuthResultCallback”类型的值?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 DataFlow Apache Beam 中创建通用日期转换类

AWS DynamoDB - 转换器类 - “错误请求,无法解析JSON”

类 Illuminate\Routing\Redirector 的对象无法转换为 int laravel

如何修复类 Illuminate\Database\Eloquent\Collection 的对象无法转换为 int

类 stdClass 的对象无法转换为字符串错误

类 Illuminate\Support\Facades\Date 的对象无法转换为字符串 [重复]