ios - '无效的文档参考。尝试编辑/删除新条目时,文档引用必须具有偶数段
问题描述
首次加载我的应用程序时,我可以删除登录的用户文档。但是,如果我创建一个新条目,长按表格视图中的新条目并选择删除,我会崩溃。我认为这与未保存文档 ID 有关,但我不知道为什么。如果在应用程序关闭并重新打开后删除相同的新创建条目,那么它将毫无问题地删除,但如果我让应用程序保持打开状态并在创建新文档后立即删除,它将崩溃。
class BudgetViewController: UIViewController: {
var budgetData = [Transaction]()
func showAdd() {
let modalViewController = AddCategory()
modalViewController.addCategoryCompletion = { newCategories in
self.budgetData.append(newCategories)
self.tableView.reloadData()
}
modalViewController.modalPresentationStyle = .overFullScreen
modalViewController.modalTransitionStyle = .crossDissolve
modalViewController.selectionDelegate = self
present(modalViewController, animated: true, completion: nil)
}
@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer){
if gestureRecognizer.state == .began {
let touchPoint = gestureRecognizer.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
let cell = CategoryCell()
var data = budgetData[indexPath.row]
let modalViewController = EditCategory()
modalViewController.deleteCategory = { row in
self.deletedRow = row
self.deleteRow()
}
modalViewController.documentID = data.trailingSubText ?? ""
modalViewController.modalPresentationStyle = .overFullScreen
modalViewController.modalTransitionStyle = .crossDissolve
present(modalViewController, animated: true, completion: nil)
modalViewController.row = indexPath.row
print("longpressed\(indexPath.row)\(data.trailingSubText)")
}
}
}
override func viewDidLoad() {
loadNewData()
}
func loadNewData() {
guard let user = Auth.auth().currentUser?.uid else { return }
db.collection("users").document(user).collection("Category").getDocuments() {
snapshot, error in
if let error = error {
print("\(error.localizedDescription)")
} else {
for document in snapshot!.documents {
let data = document.data()
let title = data["title"] as? String ?? ""
let uid = data["uid"] as? String ?? ""
let documentID = document.documentID
// let timeStamp = data["timeStamp"] as? Date
let newSourse = Transaction(title: title, dateInfo: "0% out of spent", image: UIImage.gymIcon, amount: 12, annualPercentageRate: 12, trailingSubText: documentID, uid: uid)
self.budgetData.append(newSourse)
}
self.tableView.reloadData()
}
}
}
class AddCategory: UIViewController {
@objc func saveAction(){
guard let uid = Auth.auth().currentUser?.uid else { return }
let newCategory = Transaction(title: textField.text ?? "", dateInfo: "0% out of spent", image: UIImage.gymIcon, amount: 12, annualPercentageRate: 23, trailingSubText: "", uid: uid)
db.collection("users").document(uid).collection("Category").addDocument(data: newCategory.dictionary)
self.dismiss(animated: false, completion: {
self.addCategoryCompletion?(newCategory)
})
self.dismiss(animated: false, completion: nil)
print("selected")
}
}
}
class EditCategory: UIViewController {
func deleteAction(){
guard let user = Auth.auth().currentUser?.uid else { return }
print("document::\(self.documentID)")
// let budget = textField.text
db.collection("users").document(user).collection("Category").document(documentID).delete { (err) in
if let err = err {
print(err.localizedDescription)
}else{
self.dismiss(animated: false, completion: {
self.deleteCategory?(self.row)
})
print("deleted successfully")
}
}
}
}
解决方案
根据提供的代码,当向 Firebase 添加新类别时
let newCategory = Transaction(title: textField.text ?? ...)
db.collection("users").document(uid).collection("Category").addDocument(data: newCategory
您没有首先从 Firebase 获得有效的 documentId。因此,该对象存在于您的 dataSource 中,没有 documentId,因此当您尝试删除它时,会发生崩溃。
几个选项
选项1:首先创建一个firebase引用,它将提供一个Firebase documentId,您可以在编写时将其添加到对象中。请参阅文档。像这样
let newCategoryRef = db.collection("Category").document()
let docId = newCategoryRef.documentId
...add docId to the category object, then add to dataSource
或者
选项 2:向节点添加观察者(请参阅实时更新),因此当编写新文档时,观察者事件将触发并呈现新添加的文档,其中将包含有效的 documentId,然后根据该文档制作类别对象数据并将该对象添加到您的数据源数组。在这种情况下,您不需要在写入时将其添加到 dataSource 数组中,因为它会在写入后根据观察者 .added 事件自动添加。
推荐阅读
- java - 无法在android studio中删除提醒
- angular - @ViewChild 在 Angular 组件中未定义,使用 angular2-signaturepad 库
- python - “__get__”参数之一是多余的吗?
- c# - 如何 - 在通过 Windows 服务运行 Web API 的情况下使用 SSL 证书
- firebase - Firestore 每字段安全规则
- php - 自定义 WP_Sitemaps_Provider 站点地图页面加载最后一篇博客文章
- c# - 如何将事件及其处理程序(来自表单子组件)与设计器连接?
- mysql - 为什么 r2dbc-spi 的 connectTimeout 属性的类型是 java.time.Duration 以及如何在 URL 连接中使用它?
- javascript - 如果数组包含文本,则显示名称
- c++ - 如何在递归函数中编写矩阵?