使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?

     2023-02-24     157

关键词:

【中文标题】使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?【英文标题】:Using SwiftUI, Combine, and Firebase, how do I verify that a user is signed in anonymously before linking their account to an email/password?使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是否已匿名登录? 【发布时间】:2021-01-24 01:56:24 【问题描述】:

我有一个具有以下功能的 AuthService:

func signInAnon() -> AnyPublisher<User, AuthError> 
    return Future<User, AuthError>  promise in
        Auth.auth().signInAnonymously  result, error in
            if let error = error 
                return promise(.failure(.signInAnon(description: error.localizedDescription)))
             else if let user = result?.user 
                return promise(.success(user))
            
        
    .eraseToAnyPublisher()


func linkAccount(email: String, password: String) -> AnyPublisher<User, AuthError> 
    
    let emailCredential = EmailAuthProvider.credential(withEmail: email, password: password)
    
    return Future<User, AuthError>  promise in
        Auth.auth().currentUser?.link(with: emailCredential)  result, error in
            if let error = error 
                return promise(.failure(.linkAccount(description: error.localizedDescription)))
             else if let user = result?.user 
                Auth.auth().updateCurrentUser(user)  error in
                    if let error = error 
                        return promise(.failure(.updateCurrentUser(description: error.localizedDescription)))
                     else 
                        return promise(.success((user)))
                    
                
            
        
     .eraseToAnyPublisher()

在我的 ViewModel 中,我想将用户的匿名帐户与电子邮件/密码凭据相关联。但是,在登录时,并没有发生匿名登录。

这是我的 ViewModel 中的代码:

case .signUp:

isLoading = true

authService.signInAnon()
    .timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError:  () -> AuthError in
        return .signInAnon(description: self.error?.localizedDescription))
    .sink  completion in
        switch completion 
        case let .failure(error):
            self.error = error
        case .finished:
            print("User signed in anonymously")
            self.error = nil
            
     receiveValue:  user in
        self.user = user
    
    .store(in: &cancellables)

authService.linkAccount(email: email, password: password)
    .timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError:  () -> AuthError in
        return .linkAccount(description: self.error?.localizedDescription))
    .sink  completion in
    self.isLoading = false
    switch completion 
    case let .failure(error):
        self.error = error
        self.alertIsPresented = true
        print(error.localizedDescription)
    case .finished:
        print("Sign up successful")
    
 receiveValue:  user in
    self.user = user

.store(in: &cancellables)

我遇到了问题,因为有时链接帐户的功能在匿名登录功能之前完成,出现错误。

如何有条件地编写此代码,以便检查用户是否匿名登录?如果是,请关联他们的帐户。如果不是,请匿名登录,然后关联他们的帐户。

【问题讨论】:

【参考方案1】:

以下是我对如何使用 Firebase 匿名身份验证的建议:

    一旦您的应用启动,初始化 Firebase 并检查 a 用户是否已登录。如果用户之前已登录,Firebase 身份验证会在您调用此操作之前准时获取该用户方法。 如果没有用户在场,请匿名登录。 然后您就可以开始使用所有受益于已登录用户的 Firebase 服务(例如 Firestore) 一旦用户决定实际登录,请使用任何 Firebase 身份验证提供程序获取令牌,并将其链接到现有匿名用户。顺便说一句,我建议使用比电子邮件/密码更安全的方式。

在应用启动时执行匿名登录的示例代码(取自this sample app):

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

升级到 Apple 帐户登录的示例代码(取自 the same sample app):

      case .link:
        if let currentUser = Auth.auth().currentUser 
          currentUser.link(with: credential)  (result, error) in
            if let error = error, (error as NSError).code == AuthErrorCode.credentialAlreadyInUse.rawValue 
              print("The user you're signing in with has already been linked, signing in to the new user and migrating the anonymous users [\(currentUser.uid)] tasks.")
              
              if let updatedCredential = (error as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as? OAuthCredential 
                print("Signing in using the updated credentials")
                Auth.auth().signIn(with: updatedCredential)  (result, error) in
                  if let user = result?.user 
                    currentUser.getIDToken  (token, error) in
                      if let idToken = token 
                        (self.taskRepository as? FirestoreTaskRepository)?.migrateTasks(from: idToken)
                        self.doSignIn(appleIDCredential: appleIDCredential, user: user)
                      
                    
                  
                
              
            
            else if let error = error 
              print("Error trying to link user: \(error.localizedDescription)")
            
            else 
              if let user = result?.user 
                self.doSignIn(appleIDCredential: appleIDCredential, user: user)
              
            
          
        

如果您对 Combine 的效果感兴趣,我们已经开始为 Firebase 实现 Combine 支持 - 请查看我们的 project tracker

【讨论】:

彼得,我一直在 YouTube 上观看您的视频!这非常有帮助。我几乎最终实施了你的建议。我一定会检查联合支持项目。谢谢! 这种方法的问题在于,如果用户首先在不同的设备上登录,这正是他们再次登录的原因:检索他们的旧内容。在这种情况下,链接将不起作用,因为该帐户“已被使用”。不幸的是,我无法解决这个问题,这就是我目前正在浏览 SO 的原因。 如果用户之前使用匿名身份验证在另一台设备上登录,您将无法在新设备上检索他们的用户 ID。他们需要首先在另一台设备上将其帐户链接到电子邮件或其中一个联合 IdP。有关更多详细信息,请参阅这篇文章peterfriese.dev/replicating-reminder-swiftui-firebase-part4。 @lmunck,如果您找不到特定情况的答案,请随时提出新问题。 谢谢,我做到了,但措辞相当复杂,所以我目前正在努力学习以更好地措辞。我的问题是当您使用 Google/Apple 在设备 A 上登录,然后尝试在设备 B 上关联您的帐户。在这种情况下,我在尝试关联时收到“用户已有帐户”错误。 ***.com/questions/68145638/…

如何使用 Combine 框架和 SwiftUI 发布网络请求的数据

】如何使用Combine框架和SwiftUI发布网络请求的数据【英文标题】:howtopublishthedataofanetworkrequestusingCombineframeworkandSwiftUI【发布时间】:2019-10-3012:05:05【问题描述】:我正在使用swiftUI和Combine框架以及MVVM开发一个iOS应用程序。我想在... 查看详情

在 SwiftUI 中使用 Combine 进行映射、捕获错误和分配

】在SwiftUI中使用Combine进行映射、捕获错误和分配【英文标题】:Map,catcherrorandassignwithCombineinSwiftUI【发布时间】:2021-07-3011:22:43【问题描述】:我学习使用Combine并编写了以下代码:serviceAgent.podcasts().sink(receiveCompletion:cplinswitchcplc... 查看详情

使用 Combine 和 SwiftUI 在 Realm 中观察收集结果

】使用Combine和SwiftUI在Realm中观察收集结果【英文标题】:ObserveCollectionResultsinRealmwithCombineandSwiftUI【发布时间】:2021-02-0500:37:21【问题描述】:我正在尝试thisquickstartforSwiftUIandCombine,以尝试了解如何将我的Realm数据库连接到Combine... 查看详情

使用 Combine 和 SwiftUI 对点击的按钮进行更改

】使用Combine和SwiftUI对点击的按钮进行更改【英文标题】:GetchangesonbuttontappedusingCombineandSwiftUI【发布时间】:2020-09-2410:05:48【问题描述】:在用户从Menu中选择正确的位置后尝试更改isValid。如果我先选择一个职位,然后在文本字... 查看详情

使用 SwiftUI 和 Combine 根据授权状态有条件地显示视图?

】使用SwiftUI和Combine根据授权状态有条件地显示视图?【英文标题】:UsingSwiftUIandCombinetoconditionallydisplayaviewbasedonauthorizationstatus?【发布时间】:2020-08-1015:57:55【问题描述】:我正在构建一个UI,根据HealthKit是否已获得授权,我希... 查看详情

异步下载图像时SwiftUI和Combine工作不顺畅

】异步下载图像时SwiftUI和Combine工作不顺畅【英文标题】:SwiftUIandCombinenotworkingsmoothlywhendownloadingimageasynchrously【发布时间】:2019-07-0815:11:02【问题描述】:当我尝试使用SwiftUI&Combine异步下载图像时,它工作正常。然后,我尝... 查看详情

使用 SwiftUI、Combine 和 Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?

】使用SwiftUI、Combine和Firebase,我如何在将用户的帐户链接到电子邮件/密码之前验证用户是不是已匿名登录?【英文标题】:UsingSwiftUI,Combine,andFirebase,howdoIverifythatauserissignedinanonymouslybeforelinkingtheiraccounttoanemail/password?使用SwiftUI、C... 查看详情

将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI

】将AppKit/UIKit中的Key-ValueObservation转换为Combine和SwiftUI【英文标题】:ConvertingKey-ValueObservationinAppKit/UIKittoCombineandSwiftUI【发布时间】:2021-02-1406:43:09【问题描述】:我在思考如何在SwiftUI中使用Combine时遇到了麻烦。我习惯于在AppKit... 查看详情

SwiftUI + Combine:如何将数据分配给带有动画的模型

】SwiftUI+Combine:如何将数据分配给带有动画的模型【英文标题】:SwiftUI+Combine:howtoassigndatatoamodelwithanimation【发布时间】:2021-07-2812:24:25【问题描述】:我正在使用Combine来获取用户在搜索字段中键入的匹配项。它在去抖动、去重... 查看详情

使用 SwiftUI+Combine 的数据库延迟加载

】使用SwiftUI+Combine的数据库延迟加载【英文标题】:DatabaselazyloadusingSwiftUI+Combine【发布时间】:2020-08-1307:17:08【问题描述】:我有一个数据库。我想显示数据库的内容。最明显的解决方案:@Statevaritems=Array(1...100)List(items,id:\\.self)... 查看详情

如何使用 Combine 的 CurrentValueSubject 并在 SwiftUI 视图中访问它?

】如何使用Combine的CurrentValueSubject并在SwiftUI视图中访问它?【英文标题】:HowtouseCombine\'sCurrentValueSubjectandaccessitinaSwiftUIView?【发布时间】:2020-07-2212:38:15【问题描述】:我的理解是,Combine中的CurrentValueSubject发布者适合按需访问... 查看详情

在 SwiftUI 中使用 combine 更新 Lottie Animation 时,它未能在正确的时间更新并给出意外的结果

】在SwiftUI中使用combine更新LottieAnimation时,它未能在正确的时间更新并给出意外的结果【英文标题】:WhenusingcombineinSwiftUItoupdateaLottieAnimation,itfailstoupdateattherighttimeandgivesanunexpectedresult【发布时间】:2021-02-0219:47:44【问题描述】:... 查看详情

使用 SwiftUI/Combine,如何避免在 ViewModel 中放置可取消项

】使用SwiftUI/Combine,如何避免在ViewModel中放置可取消项【英文标题】:WithSwiftUI/Combine,HowtoavoidtoputcancellablesinViewModel【发布时间】:2020-09-1115:33:02【问题描述】:我一直将DisposeBag放在带有RxSwift的MVVM中的ViewController中,就像它在本... 查看详情

SwiftUI ObjectBinding 不会使用 combine 接收来自可绑定对象的 didchange 更新

】SwiftUIObjectBinding不会使用combine接收来自可绑定对象的didchange更新【英文标题】:SwiftUIObjectBindingwon\'treceivedidchangeupdatefrombindableobjectusingcombine【发布时间】:2019-07-1610:11:35【问题描述】:我正在测试Combine框架并使用BindableObject作... 查看详情

使用 combine's Publisher 在 SwiftUI Image 中从远程 URL 异步加载图像

】使用combine\\\'sPublisher在SwiftUIImage中从远程URL异步加载图像【英文标题】:LoadingimagefromremoteURLasynchronouslyinSwiftUIImageusingcombine\'sPublisher使用combine\'sPublisher在SwiftUIImage中从远程URL异步加载图像【发布时间】:2020-11-1608:33:27【问题描... 查看详情

Combine + SwiftUI 中的最佳数据绑定实践?

】Combine+SwiftUI中的最佳数据绑定实践?【英文标题】:Bestdata-bindingpracticeinCombine+SwiftUI?【发布时间】:2020-01-1013:08:34【问题描述】:在RxSwift中,很容易将Driver或ViewModel中的Observable绑定到ViewController中的某个观察者(即UILabel)。... 查看详情

swiftui combine 无法获取数据 [关闭]

】swiftuicombine无法获取数据[关闭]【英文标题】:swiftuicombinecan\'tfetchdata[closed]【发布时间】:2020-10-2407:41:41【问题描述】:我写代码,在Xcode中没有错误,但我无法使用combine获取数据,为什么?没有结合这个API工作,没有结合)... 查看详情

使用 Combine SwiftUI 获取图像并设置它们会使应用程序冻结

】使用CombineSwiftUI获取图像并设置它们会使应用程序冻结【英文标题】:FetchingimagesandsettingthemmakestheappfreezeusingCombineSwiftUI【发布时间】:2019-12-2316:32:25【问题描述】:您好,我目前在从url获取图像时显示图像时遇到问题。因此,... 查看详情