SwiftUI中Firebase无当前用户ID时添加用户名按钮不显示问题
问题根源
你当前的实现存在两个致命逻辑错误,导致多用户场景下按钮展示异常:
- 每次拉取全量所有用户的档案数据,再通过遍历List做筛选,只要数据库存在其他用户的数据,遍历到非当前用户的条目时就会误触发分支
- 筛选条件
|| model.listTwo.count > 0完全没有和当前用户UID绑定,只要数据库里有任意一条用户记录,筛选就会通过,和你要判断的「当前用户是否有档案」没有任何关系 - 把单用户的档案操作放在List循环里实现本身就是结构错误——当前登录用户只会对应一条档案记录,不需要用列表组件承载。
修复方案
核心思路是:不要拉全量用户数据,直接针对当前登录UID查询是否存在对应档案,用单独的状态值标记当前用户是否已创建档案,完全移除多余的List遍历逻辑。
1. 重构ViewModel,只查询当前用户档案
final class ListViewModel: ObservableObject { @Published var list = Clubs // 仅存储当前登录用户的档案信息,不再拉取全量用户数据 @Published var currentUserProfile: ProfileInfo? = nil @Published var isLoading = false // 按UID精确查询当前用户档案 func fetchCurrentUserProfile(uid: String) { isLoading = true let db = Firestore.firestore() db.collection("profileInfo") .whereField("userID", isEqualTo: uid) .getDocuments { [weak self] snapshot, error in guard let self = self else { return } DispatchQueue.main.async { self.isLoading = false if let _ = error { print("查询用户档案失败") return } // 查到记录说明用户已创建档案 if let doc = snapshot?.documents.first { self.currentUserProfile = ProfileInfo( id: doc.documentID, userID: doc["userID"] as? String ?? "", userName: doc["userName"] as? String ?? "", exists: doc["exists"] as? Bool ?? true ) } else { // 无记录则为新用户 self.currentUserProfile = nil } } } } // 更新用户名 func updateClub(userID: String, userName: String) { let db = Firestore.firestore() db.collection("profileInfo") .whereField("userID", isEqualTo: userID) .getDocuments { [weak self] (snap, err) in guard err == nil, let docs = snap?.documents else { print("更新失败") return } for doc in docs { DispatchQueue.main.async { doc.reference.updateData(["userName": userName]) } } // 更新完成后刷新当前用户数据 self?.fetchCurrentUserProfile(uid: userID) } } // 新增用户档案 func addProfileData(userID: String, userName: String, exists: Bool){ let db = Firestore.firestore() db.collection("profileInfo") .addDocument(data: ["userID": userID, "userName": userName, "exists": exists]) { [weak self] error in guard error == nil else { return } // 新增完成后刷新当前用户数据,自动切换到更新视图 self?.fetchCurrentUserProfile(uid: userID) } } }
2. 重写Settings视图,移除多余List逻辑
不需要用List承载单用户的档案操作,直接根据currentUserProfile的状态展示对应UI即可:
struct Settings: View { let exampleColor : Color = Color(red: 150/255, green: 185/255, blue: 208/255) @AppStorage("log_Status") var log_Status = true @State var userName = "" @ObservedObject var model = ListViewModel() // 安全解包当前用户UID var currentUID: String? { Auth.auth().currentUser?.uid } var body: some View { if log_Status, let uid = currentUID { ZStack{ Image("Wallpaper10").resizable().edgesIgnoringSafeArea(.all) VStack(spacing: 20) { Form { Group { Text("Your current profile name: ") // 加载状态 if model.isLoading { ProgressView() .frame(maxWidth: .infinity, alignment: .center) } // 已存在档案,展示更新UI else if let profile = model.currentUserProfile { Text(profile.userName) .font(.headline) .frame(maxWidth: .infinity, alignment: .center) .fontWeight(.semibold) TextField("Update your user name", text: $userName) .textFieldStyle(RoundedBorderTextFieldStyle()) .multilineTextAlignment(.center) Button { model.updateClub(userID: uid, userName: userName) userName = "" } label: { Text("Submit change") .frame(maxWidth: .infinity, alignment: .center) .fontWeight(.semibold) } } // 无档案,展示新增UI else { TextField("Add your profile name", text: $userName) .textFieldStyle(RoundedBorderTextFieldStyle()) .multilineTextAlignment(.center) Button { model.addProfileData(userID: uid, userName: userName, exists: true) userName = "" } label: { Text("Submit change") .frame(maxWidth: .infinity, alignment: .center) .fontWeight(.semibold) } } } } Button("Logout") { GIDSignIn.sharedInstance.signOut() try? Auth.auth().signOut() withAnimation{ log_Status = false } } } } .onAppear { // 页面展示时拉取当前用户档案 model.fetchCurrentUserProfile(uid: uid) } } } init(){ UITableView.appearance().backgroundColor = .clear UITableViewCell.appearance().backgroundColor = .clear } }
3. 修正ProfileInfo模型
你后续更新中移除userID字段的写法是错误的,必须保留userID字段才能做UID精确匹配,模型改回如下结构:
struct ProfileInfo: Identifiable, Codable { var id: String var userID: String var userName: String var exists: Bool }
优化说明
- 不再拉取全量用户数据,仅查询当前用户的档案记录,减少Firestore读次数,从根源避免多用户数据串扰
- 把用户档案状态抽成独立变量,判断逻辑清晰,不会出现遍历其他用户数据导致的按钮误展示问题
- 新增/修改用户名后自动刷新用户状态,无需手动操作即可自动切换对应UI
- 增加加载状态,避免数据请求过程中UI闪烁误判
内容的提问来源于stack exchange,提问作者user19202930
相关产品推荐
相关产品推荐

