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

SwiftUI+Firebase:数据库用户权限复选框修改及代码优化问题

SwiftUI Firebase用户权限修改与代码简化解决方案

问题1:无法修改用户权限(提示user为let常量)

原因:List遍历出的user是不可变的let常量,且User是值类型struct,直接修改内部属性会报错。此外修改后需要同步更新Firebase数据库,不能仅修改本地数据。

解决步骤:

  1. 在AdministratorManager中添加修改权限的方法,通过用户number(文档ID)定位用户,更新本地数组并同步Firebase:
func updatePermission(forUserNumber number: String, atIndex index: Int, newValue: Bool) {
    guard let userIndex = users.firstIndex(where: { $0.number == number }) else { return }
    // 更新本地数据
    users[userIndex].permessi[index] = newValue
    // 同步Firebase数据库
    DatabaseFirestore.collection("Admins").document(number).updateData([
        "Permessi": users[userIndex].permessi
    ]) { error in
        if let error = error {
            print("更新权限失败: \(error.localizedDescription)")
        }
    }
}
  1. 在View中调用该方法替代直接修改user属性:
    将原代码中的user.permessi[0].toggle()替换为administratorManager.updatePermission(forUserNumber: user.number, atIndex: 0, newValue: !user.permessi[0])

问题2:ForEach简化代码的错误

原代码语法错误,且无法获取权限索引以修改对应值。需遍历权限数组的索引,同时获取对应Bool值:

修正后的ForEach写法:

ForEach(user.permessi.indices, id: \.self) { index in
    let isEnabled = user.permessi[index]
    HStack {
        Image(systemName: isEnabled ? "checkmark.square.fill" : "square")
            .foregroundColor(isEnabled ? Color(UIColor.systemBlue) : Color.secondary)
            .onTapGesture {
                administratorManager.updatePermission(forUserNumber: user.number, atIndex: index, newValue: !isEnabled)
            }
        Text("\(index)")
            .onTapGesture {
                administratorManager.updatePermission(forUserNumber: user.number, atIndex: index, newValue: !isEnabled)
            }
            .padding(1)
    }
}

说明:通过permessi.indices遍历索引,id: \.self保证元素唯一性,从而拿到对应权限的索引并调用更新方法。

完整修正后的代码

User结构(无需修改,确保Identifiable)

struct User: Identifiable {
    var id: String = UUID().uuidString
    var name: String
    var surname: String
    var school: String
    var orari: [String]
    var permessi: [Bool]
    var number: String
}

AdministratorManager的fetchData与新增updatePermission方法

class AdministratorManager: ObservableObject {
    @Published var users: [User] = []
    
    func fetchData(collection: String) {
        DatabaseFirestore.collection(collection).addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No documents")
                return
            }
            
            self.users = documents.map { (queryDocumentSnapshot) -> User in
                let data = queryDocumentSnapshot.data()
                let name = data["Nome"] as? String ?? ""
                let surname = data["Cognome"] as? String ?? ""
                let school = data["Scuola"] as? String ?? ""
                let orari = data["Orari"] as? [String] ?? []
                let permessi = data["Permessi"] as? [Bool] ?? []
                let number = queryDocumentSnapshot.documentID
                
                return User(name: name, surname: surname, school: school, orari: orari, permessi: permessi, number: number)
            }
        }
    }
    
    func updatePermission(forUserNumber number: String, atIndex index: Int, newValue: Bool) {
        guard let userIndex = users.firstIndex(where: { $0.number == number }) else { return }
        users[userIndex].permessi[index] = newValue
        
        DatabaseFirestore.collection("Admins").document(number).updateData([
            "Permessi": users[userIndex].permessi
        ]) { error in
            if let error = error {
                print("权限更新失败: \(error.localizedDescription)")
            }
        }
    }
}

最终View代码

List(administratorManager.users) { user in
    HStack {
        VStack(alignment: .leading) {
            Text(user.number).font(.subheadline)
            Text(user.name).font(.subheadline)
            Text(user.surname).font(.subheadline)
            
            VStack(alignment: .leading){
                Text("Permessi")
                    .font(.title2)
                    .fontWeight(.bold)
                    .padding(1)
                
                // 用ForEach简化权限列表
                ForEach(user.permessi.indices, id: \.self) { index in
                    let isEnabled = user.permessi[index]
                    HStack{
                        Image(systemName: isEnabled ? "checkmark.square.fill" : "square")
                            .foregroundColor(isEnabled ? Color(UIColor.systemBlue) : Color.secondary)
                            .onTapGesture {
                                administratorManager.updatePermission(forUserNumber: user.number, atIndex: index, newValue: !isEnabled)
                            }
                        Text("\(index)")
                            .onTapGesture {
                                administratorManager.updatePermission(forUserNumber: user.number, atIndex: index, newValue: !isEnabled)
                            }
                            .padding(1)
                    }
                }
            }
        }
    }
}
.onAppear() {
    administratorManager.fetchData(collection: "Admins")
}

内容的提问来源于stack exchange,提问作者mickele29

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 01:15:11