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

如何在Firebase Firestore中获取Document ID以删除TableView对应数据

解决TableView左滑删除Firestore数据时无法获取Document ID的问题

问题根源

  • 添加员工时手动传入空的documentID并存入Firestore,而Firestore自动生成的文档ID无需存储在文档数据中,应从DocumentSnapshot直接获取
  • 加载数据时仅通过文档的data()解析employee对象,但data()里没有正确的文档ID(存入时为空),未利用DocumentSnapshot自带的documentID属性
  • 删除操作使用固定字符串"UID",未调用对应员工的实际文档ID

具体修改步骤

1. 重构Employee结构体

去掉不必要的documentID存储字段,调整初始化方法支持直接传入文档ID:

import UIKit
import Firebase
import Firestore

protocol DocumentSeriziable {
    init?(dictionary:[String:Any], documentID: String)
}

// 结构体名遵循Swift规范改为大写开头
struct Employee {
    var name: String
    var adress: String
    var timeStamp: Date
    var documentID: String
    
    var dictionary:[String : Any] {
        return[
            "name": name,
            "adress": adress,
            "timeStamp": timeStamp
        ]
    }
}

extension Employee : DocumentSeriziable {
    init?(dictionary: [String : Any], documentID: String) {
        guard let name = dictionary["name"] as? String,
              let adress = dictionary["adress"] as? String,
              let timeStamp = dictionary["timeStamp"] as? Date else { return nil }
        self.init(name: name, adress: adress, timeStamp: timeStamp, documentID: documentID)
    }
}

2. 修正数据加载方法

从DocumentSnapshot中提取documentID并传入Employee初始化:

func loadData() {
    db.collection("employee").getDocuments() { querySnapshot, error in
        if let error = error {
            print("\(error.localizedDescription)")
        } else {
            self.employeeArray = querySnapshot!.documents.compactMap { document in
                Employee(dictionary: document.data(), documentID: document.documentID)
            }
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    }
}

3. 修正实时监听更新逻辑

同样从diff.document中获取文档ID:

func checkForUpdates() {
    db.collection("employee").whereField("timeStamp", isGreaterThan: Date())
        .addSnapshotListener { querySnapshot, error in
            guard let snapshots = querySnapshot else { return }
            
            snapshots.documentChanges.forEach { diff in
                if diff.type == .added {
                    if let newEmployee = Employee(dictionary: diff.document.data(), documentID: diff.document.documentID) {
                        self.employeeArray.append(newEmployee)
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    }
                }
            }
        }
}

4. 优化添加员工流程

无需手动传入空的documentID,Firestore自动生成后可通过实时监听同步本地数据:

@IBAction func addEmployee(_ sender: Any) {
    let composeAlert = UIAlertController(title: "Add Employee", message: "Add Employee", preferredStyle: .alert)
    
    composeAlert.addTextField { textField in
        textField.placeholder = "Name"
    }
    
    composeAlert.addTextField { textField in
        textField.placeholder = "Adress"
    }
    
    composeAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    
    composeAlert.addAction(UIAlertAction(title: "Add Employee", style: .default, handler: { [weak self] action in
        guard let self = self,
              let name = composeAlert.textFields?.first?.text, !name.isEmpty,
              let adress = composeAlert.textFields?.last?.text, !adress.isEmpty else { return }
        
        let newEmployee = Employee(name: name, adress: adress, timeStamp: Date(), documentID: "")
        
        self.db.collection("employee").addDocument(data: newEmployee.dictionary) { error in
            if let error = error {
                print("Error adding document: \(error.localizedDescription)")
            } else {
                print("Document added successfully")
            }
        }
    }))
    
    self.present(composeAlert, animated: true, completion: nil)
}

5. 实现正确的删除逻辑

从本地数组获取对应员工的documentID,删除Firestore文档后同步更新本地数据和TableView:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        let employeeToDelete = employeeArray[indexPath.row]
        db.collection("employee").document(employeeToDelete.documentID).delete { [weak self] err in
            guard let self = self else { return }
            if let err = err {
                print("Error removing document: \(err)")
            } else {
                print("删除成功")
                self.employeeArray.remove(at: indexPath.row)
                DispatchQueue.main.async {
                    tableView.deleteRows(at: [indexPath], with: .automatic)
                }
            }
        }
    }
}

6. 清理无用代码

删除原代码中的UID()方法,该方法已无存在必要。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:58