You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 10:15:38