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
相关产品推荐
相关产品推荐

