微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将其他用户数据保存到Cloud Firestore?

如何解决如何将其他用户数据保存到Cloud Firestore?

我成功将其他firstNamelastNameemailgender保存到Cloud Firestore上的集合中。

我现在希望能够在我的应用程序的设置屏幕中使用和更改此数据。例如:如果用户想更改电子邮件。问题是该电子邮件保存在Firebase Auth中,但也保存在Cloud Firestore的profiles集合中。您可以同时更改两者吗?

这是我的SessionStore:

import Foundation
import Combine
import Firebase

class SessionStore: ObservableObject {
    
  @Published var profile: UserProfile?
  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
      }
    })    
  }
    
  private var profileRepository = UserProfileRepository()
   
  func signUp(email: String,password: String,firstName: String,lastName: String,gender: 
    String,completion: @escaping (_ profile: UserProfile?,_ error: Error?) -> Void) {
    Auth.auth().createuser(withEmail: email,password: password) { (result,error) in
      if let error = error {
        print("Error signing up: \(error)")
        completion(nil,error)
        return
      }
            
      guard let user = result?.user else { return }
      print("User \(user.uid) signed up.")
            
      let userProfile = UserProfile(uid: user.uid,email: user.email ?? "",firstName: firstName,lastName: lastName,gender: gender)
      self.profileRepository.createProfile(profile: userProfile) { (profile,error) in
        if let error = error {
          print("Error while fetching the user profile: \(error)")
          completion(nil,error)
          return
        }
        self.profile = profile
        completion(profile,nil)
      }
    }
  }
    
  func signIn(email: String,_ error: Error?) -> Void) {
    Auth.auth().signIn(withEmail: email,error) in
      if let error = error {
        print("Error signing in: \(error)")
        completion(nil,error)
        return
      }
            
      guard let user = result?.user else { return }
      print("User \(user.uid) signed in.")
            
      self.profileRepository.fetchProfile(userId: user.uid) { (profile,error)
          return
        }
                
        self.profile = profile
        completion(profile,nil)
      }
    }
  }
    
  func signOut() {
    do {
      try Auth.auth().signOut()
      self.session = nil
      self.profile = nil
    }
    catch let signOutError as NSError {
      print("Error signing out: \(signOutError)")
    }
  }
    
  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
    }
  }
}

我的个人资料存储库:

import Foundation
import Combine
import Firebase
import FirebaseFirestoreSwift

struct UserProfile: Codable {
  var uid: String
  var email: String
  var firstName: String
  var lastName: String
  var gender: String
}

class UserProfileRepository: ObservableObject {
  private var db = Firestore.firestore()
    
  func createProfile(profile: UserProfile,_ 
    error: Error?) -> Void) {
    do {
      let _ = try db.collection("profiles").document(profile.uid).setData(from: profile)
      completion(profile,nil)
    }
    catch let error {
      print("Error writing to Firestore: \(error)")
      completion(nil,error)
    }
  }
    
  func fetchProfile(userId: String,_ error: 
    Error?) -> Void) {
    db.collection("profiles").document(userId).getDocument { (snapshot,error) in
      let profile = try? snapshot?.data(as: UserProfile.self)
      completion(profile,error)
    }
  }
}

和设置视图:

import SwiftUI
import FirebaseAuth
import Firebase

struct SettingsView: View {    
  @State var showEdit = false
  var genderOptions = ["Male","Female","Other"]
  @StateObject var viewmodel = UserProfileRepository()
  @State var firstName: String = ""
  @State var lastNameName: String = ""
  @State var email: String = ""
  @State var gender: String = ""
    
  var body: some View {
    ScrollView {
      vstack {
        HStack {
          Text("Settings")
        }
        .padding()
                
        vstack {
          Spacer()
          HStack {
            Image(systemName: "person.fill")
            if showEdit == true {
              TextField("First Name",text: $firstName)
                .autocapitalization(.words)
                .keyboardType(.default)
                .font(.subheadline)
            } 
            else {
              Text("")
                .font(.subheadline)
                .padding()
                .onTapGesture {
                  showEdit = true
                }
              }
            }
            HStack {
              Image(systemName: "envelope.fill")
              if showEdit == true {
                TextField("Email",text: $email)
                  .autocapitalization(.none)
                  .keyboardType(.emailAddress)
                  .font(.subheadline)
              } 
              else {
                Text("")
                  .font(.subheadline)
                  .padding()
                  .onTapGesture {
                    showEdit = true
                  }
              }
              HStack {
                Image(systemName: "figure.wave")
                if showEdit == true {
                  Picker(selection: $gender,label: Text("")) {
                    ForEach(genderOptions,id: \.self) {
                      Text($0)
                        .font(.footnote)
                    }
                  }
                  .pickerStyle(SegmentedPickerStyle())
                  .frame(maxWidth: .infinity)
                  .padding()
                }
                else {
                  Text("")
                    .font(.subheadline)
                    .padding()
                    .onTapGesture {
                      showEdit = true
                    }
                }
                Spacer()
              }
            }
            if showEdit == true {
              Image(systemName: "checkmark")
                .onTapGesture{
                  showEdit.toggle()
                }
            }  
          }
          .onAppear {
          }
    }
  }
}

struct SettingsView_Previews: PreviewProvider {
  static var previews: some View {
    SettingsView()
  }
}

解决方法

一些注意事项:

  1. 无需在您的didChange = PassthroughSubject上实现SessionStore-一旦您更改了任何@Published属性,就会通知所有订阅者。
  2. 无需实现自己的User结构-只需使用从Firebase Auth获得的结构即可-它具有您需要照顾的所有属性。
  3. Settings 视图中,尝试将整个视图包装在NavigationView中,将navigationBarTitle设置为Settings-这应该为您提供典型的设置UI 。请参阅this implementation以供参考。

关于您的问题:如果要在Firebase Auth中更新用户的数据,则需要使用Firebase Auth的功能来这样做:

  1. 更新其基本个人资料信息(docs
  • 使用createProfileChangeRequest()
  • 在请求对象上设置新值
  • 致电changeRequest?.commitChanges进行更改
  1. 更新他们的电子邮件(docs
  • 使用updateEmail(to: email)

一旦这些调用成功完成(使用相应的回调,记住这些是异步操作),您就可以在Firestore的profiles集合中更新用户的信息。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。