You need to enable JavaScript to run this app. SwiftUI操作Firestore更新数据重复、删除无响应问题求助
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI操作Firestore更新数据重复、删除无响应问题求助

问题根因

  • Project模型中@DocumentID属性设置了错误的默认值:@DocumentID var id: String? = UUID().uuidString。@DocumentID是Firebase FirestoreSwift提供的属性包装器,作用是自动将Firestore文档的ID映射到该属性,给它设置本地UUID的默认值后,从Firestore读取数据时该属性不会被正确赋值为真实的Firestore文档ID,会保留本地生成的UUID值。编辑时因为本地ID和Firestore真实ID不匹配,updateOrAddProject方法找不到对应文档就会触发新增逻辑,出现重复数据;删除时也因为ID错误找不到对应文档,所以没有响应。
  • Project模型中直接使用了SwiftUI的Color类型,该类型默认不遵守Codable协议,Firestore无法直接解析存储,会导致编解码失败、数据字段丢失。

修复步骤

1. 为Color添加Codable支持

新增扩展让SwiftUI Color支持编解码,方便Firestore存储:

extension Color: Codable {
    enum CodingKeys: String, CodingKey {
        case red, green, blue, alpha
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let red = try container.decode(Double.self, forKey: .red)
        let green = try container.decode(Double.self, forKey: .green)
        let blue = try container.decode(Double.self, forKey: .blue)
        let alpha = try container.decode(Double.self, forKey: .alpha)
        self.init(red: red, green: green, blue: blue, opacity: alpha)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        let uiColor = UIColor(self)
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
        uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        try container.encode(Double(red), forKey: .red)
        try container.encode(Double(green), forKey: .green)
        try container.encode(Double(blue), forKey: .blue)
        try container.encode(Double(alpha), forKey: .alpha)
    }
}

2. 修正Project模型

移除id的默认UUID赋值,同时把id加入CodingKeys保证编解码正常:

struct Project: Identifiable, Codable{
    @DocumentID var id: String? 

    var title: String
    // var creator: String = Auth.auth().currentUser?.displayName ?? "N/A"
    var color: Color
    var assignedStudents: [String]
    var notes: String

    enum CodingKeys: String, CodingKey {
        case id
        case title
        //case creator
        case color
        case assignedStudents
        case notes
     }
}

3. 校验详情页ViewModel初始化逻辑

确保ProjectDetailsView中初始化ProjectViewModel时,传入的是从列表页拿到的、已经正确赋值了Firestore文档ID的project实例,不要在详情页内部新建空的Project实例传入ViewModel,否则id为空会触发新增逻辑。列表页的NavigationLink应该按如下方式编写:

NavigationLink(destination: ProjectDetailsView(viewModel: ProjectViewModel(project: project)))

4. 清理冗余代码

删除ProjectsListView中未使用的@ObservedObject var viewModel2 = ProjectViewModel(),避免不必要的资源占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 04:09:02