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

SwiftUI中Firebase Firestore无法保存数据问题求助

Firestore无法保存数据问题排查

现象

Firestore数据保存失败

代码实现

模型定义

struct Box: Identifiable, Hashable, Codable {
    @DocumentID var id: String?
    var boxName: String
    var boxSize: String

    enum CodingKeys: String, CodingKey {
        case id
        case boxName
        case boxSize
    }

    var dictionary: [String: Any] {
        let data = (try? JSONEncoder().encode(self)) ?? Data()
        return (try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any]) ?? [:]
    }
}

ViewModel实现

class BoxViewModel: ObservableObject {
    @Published var box: Box
    private var db = Firestore.firestore()

    init(box: Box = CashBox(boxName: "", boxSize: "")) {
        self.box = box
    }

    private func addNewBox(_ box: Box){
        print("the name  \(box.boxName)")
        let _ = db.collection("Box")
            .addDocument(data: box.dictionary)
    }

    func addBox() {
        self.addNewBox(box)
    }
    
    func setBoxData(boxName: String, boxSize: String){
        self.box.boxName = boxName
        self.box.boxSize = boxSize
    }
}

视图代码

struct CashBoxView: View {
    @State var boxName = ""
    @State var boxSize = ""
    @EnvironmentObject var boxViewModel: BoxViewModel

    var body: some View {
        Text("Enter box name")
        TextField("", text: $boxName)

        Text("Enter box size")
        TextField("", text: $boxSize)

        Button(action: {
            boxViewModel.setBoxData(boxName: boxName, boxSize: boxSize)
            boxViewModel.addBox()
        }) {
            Text("Done")
        }
    }
}

排查方向

从你的描述看,box.boxName能正常打印,说明对象数据没问题,以下是几个核心排查点:

  1. EnvironmentObject注入验证
    确认父视图已通过.environmentObject(BoxViewModel())完成ViewModel注入。如果未注入,@EnvironmentObject会直接触发崩溃,但既然能打印数据,大概率已注入,可再检查注入逻辑是否覆盖当前视图层级。

  2. Firestore权限规则
    默认Firestore规则仅允许认证用户读写数据,如果当前未做用户登录,数据会被拦截。可临时修改规则测试(测试后务必改回安全规则):

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if true;
        }
      }
    }
    
  3. 字典转换逻辑问题
    当前通过JSONEncoder转Data再转字典的方式存在不确定性,比如@DocumentID标记的可选id可能编码异常。建议手动构建字典替代:

    var dictionary: [String: Any] {
        var dict: [String: Any] = [
            "boxName": boxName,
            "boxSize": boxSize
        ]
        if let id = id {
            dict["id"] = id
        }
        return dict
    }
    
  4. 错误捕获缺失
    当前addDocument未处理错误,添加回调获取具体失败原因:

    db.collection("Box").addDocument(data: box.dictionary) { error in
        if let error = error {
            print("保存失败原因: \(error.localizedDescription)")
        } else {
            print("数据保存成功")
        }
    }
    
  5. ViewModel初始化笔误
    初始化代码中写的是CashBox(boxName: "", boxSize: ""),但你的模型是Box,这里是明显笔误,需改为Box(boxName: "", boxSize: ""),避免初始化异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 07:45:34