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

