问题
Right now my app is crashing when a collection already exists in Firebase Firestore. I want to catch this error when it happens, but my current implementation doesn't catch anything as the addSnapshotListener()
method does not throw any error.
Current Code
let db = Firestore.firestore()
do {
try db.collection(chatName).addSnapshotListener { (Query, Error) in
if Error != nil || Query?.documents != nil {
let alert = UIAlertController(title: "Chat Name Already Exists", message: "This chat name already exists, try again with a different name", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: { (UIAlertAction) in
alert.dismiss(animated: true, completion: nil)}))
AllChatsViewController().present(alert, animated: true)
completion()
}
else {
self.addChatToProfile(withName: chatName) {
completion()
}
}
}
}
catch {
let alert = UIAlertController(title: "Chat Name Already Exists", message: "This chat name already exists, try again with a different name", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: { (UIAlertAction) in
alert.dismiss(animated: true, completion: nil)}))
AllChatsViewController().present(alert, animated: true)
completion()
}
Error After App Crashes
Thread 1: "Invalid collection reference. Collection references must have an odd number of segments, but has 0"
How can I catch this error so I can display an UIAlertController with the error?
回答1:
I would use a different approach.
To test if a collection exists, read that collection by name and determine if there are any documents via snapshot.count equals 0
The gotcha here is that a collection could have a large amount of data and there's no reason to read all of that in or attach a listener so we need to use a known field within that collection to limit the results.
I would suggest a function with a closure that returns true if the collection exists, false if not and then take action based on that result.
You'll need the name of the collection you want to test and then the name of a known field within that collection to query for to limit the results.
The field name is important in that if the collection has 1M documents, you don't want to read them all in - you just want to read one and .orderBy with a limit will do that.
So here's a calling function
func checkCollection() {
self.doesCollectionExist(collectionName: "test_collection", fieldName: "msg", completion: { isEmpty in
if isEmpty == true {
print("collection does not exist")
} else {
print("collection found!")
}
})
}
and then the function that checks to see if the collection exists by reading one document and returns false if not, true if it does.
func doesCollectionExist(collectionName: String, fieldName: String, completion: @escaping ( (Bool) -> Void ) ) {
let ref = self.db.collection(collectionName)
let query = ref.order(by: fieldName).limit(toLast: 1)
query.getDocuments(completion: { snapshot, error in
if let err = error {
print(err.localizedDescription)
return
}
if snapshot!.count == 0 {
completion(true)
} else {
completion(false)
}
})
}
回答2:
That error doesn't have anything to do with a collection not existing The error suggests that chatName
is an empty string, which is an invalid parameter. Instead of catching an error, you should instead first validate that chatName
is a valid collection name string before sending it to the Firestore API.
If you query a collection that doesn't exist, you won't get that error message at all. Instead, you will simply get no documents in the result set.
回答3:
you will make something like this:
Firestore.firestore().collection(chatName).addSnapshotListener { (query, error) in
if let error = error {
//in this part you have the error, do something like present alert with error or something you want
print(error)
}
// in this part the success
来源:https://stackoverflow.com/questions/64308664/how-to-catch-error-when-firestore-collection-already-exists