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

Firebase调用setData时无法将更新数据保存至Firestore问题

问题根因

问题出在setData(_:merge:)的merge行为上:开启merge: true时,Firestore会对Map类型的字段做深度合并,不会自动删除新传入数据中不存在的旧键。
举个实际场景:原数据库里ingredientItem字段存的是["1块": "鸡胸肉", "1勺": "盐"],你删除盐之后传入的新ingredientList是["1块": "鸡胸肉"],merge逻辑只会更新新旧字典共有的键、追加新字典里新增的键,新字典里缺失的旧键(即被删除的"1勺": "盐")会完整保留在原字段里,最终表现就是删除操作不生效。
新增食材时因为是往字典里追加键值,merge逻辑只会新增内容不会暴露问题,所以你会观察到只有删除场景失效。你之前用updateData能正常运行,是因为updateData对传入的顶层字段做整体替换,不会触发嵌套深度合并,刚好符合你要整体覆盖ingredientItem字段的需求。

修复方法

选最简便的方案即可:

  • 直接替换成你之前验证可用的updateData方法,把原来的setData调用改成下面的代码:
FirebaseManager.shared.firestore
    .collection("users")
    .document(uid)
    .collection("userRecipes")
    .document(document.documentID)
    .updateData(["ingredientItem" : ingredientList]) { error in
        if let error = error {
            print("食材更新失败: \(error.localizedDescription)")
        } else {
            print("Updated Recipe")
        }
    }
  • 如果你坚持要用setData,就需要手动比对新旧字典的键差集,给所有被删除的键传入FieldValue.delete()标记删除,但这个方案冗余度高,完全没必要。
额外隐患提示

你当前在View内部直接初始化@ObservedObject var rm = RecipeLogic()的写法有问题,View重绘时会反复重新创建RecipeLogic实例,很容易引发后续状态错乱。如果是iOS14及以上版本,把这里改成@StateObject var rm = RecipeLogic()即可;如果兼容更低版本,建议在父视图初始化rm实例后再传入当前View。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:39:23