首页 > 解决方案 > NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED

问题描述

I got an error

"Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: Invalid document reference. Document references must have an even number of segments, but documents has 1' terminating with uncaught exception of type NSException"

Here is my code and I don't known what wrong with my code ;-;

   let docRef = db.collection("documents").document(self.txt_email.text!)
                    print(docRef.getDocument{ (document, error)
                        in print("DOC", document?.exists)
                        if(document?.exists == true){
                            print("EXISTS")
                        }else{
                            print("NOT EXISTS")
                            db.collection("documents").document(self.txt_email.text!).setData([:])
                        }
                    })

And here is my full Login code

      let db = Firestore.firestore()
            db.collection("Person").whereField("email", isEqualTo: email).getDocuments() { (querySnapshot, err) in
                if let err = err {
                    print("Error getting documents: \(err)")
                } else {
                    
                    
                    let docRef = db.collection("documents").document(self.txt_email.text!)
                    print(docRef.getDocument{ (document, error)
                        in print("DOC", document?.exists)
                        if(document?.exists == true){
                            print("EXISTS")
                        }else{
                            print("NOT EXISTS")
                            db.collection("documents").document(self.txt_email.text!).setData([:])
                        }
                    })

              
                    
                    
                    
                    
       
                    let document = querySnapshot!.documents.first
                    let account = Mapper<Account>().map(JSONObject: document!.data())!
                    ManageCacheObject.saveCurrentAccount(account)
                    
                    self.txt_email.text = ""
                    self.txt_password.text = ""
                    
                    let mainViewController:MainViewController?
                    mainViewController = UIStoryboard.mainViewController()
                    self.navigationController?.pushViewController(mainViewController!, animated: true)
                    hud.dismiss()
                }

标签: swiftfirebasegoogle-cloud-firestore

解决方案


代码存在一些问题,还有一个整体设计潜在问题。

这是第一个问题

self.txt_email.text!

如果 text 为 nil 会发生什么?然后你的代码爆炸了(根据你的问题)。这 !表示这是一个可选的,所以它可能是 nil。

最好通过使用 nil 合并运算符来设置默认值或完全避免调用它的 nil 来处理这个问题。

guard let email = self.txt_email.text else { return }
let docRef = db.collection("documents").document(email)

这是第二个问题。Firestore 是异步的,闭包之后的代码将闭包中的代码之前执行。所以在这个firebase调用中

print( docRef.getDocument{ (document, error) in

闭包之后的行

let document = querySnapshot!.documents.first

将在闭包之前执行,在某些情况下可能会导致崩溃 - 取决于在闭包中操作的数据数据中/正在执行的操作。在这个用例中,这可能不是问题,但需要注意。

设计明智 - 电子邮件地址可以包含 documentId 中应避免的字符。

另外,如果电子邮件地址发生变化会怎样?您必须更改整个数据库中对该电子邮件的所有引用。

您的结构未包括在内,所以我不知道它是什么,但通常最好将 documentId 与文档包含的数据区分开来。例如

People              //collection
   person_id_0      //documentId is auto generated by Firestore
      person_name   //fields
      email
   person_id_1      //document
      person_name   //fields
      email


documents           //collection
   document_0       //document
      email         //field
   document_1
      email

因此,一旦您拥有 person_id_0 的电子邮件,您就可以查询文档集合以查看它是否存在。如果电子邮件更改,您只需在一处更改。同样,这避免了由可能出现在电子邮件地址中的字符引起的问题。


推荐阅读