#swift #firebase #google-cloud-firestore #try-catch
#swift #firebase #google-облако-firestore #попробуйте-поймайте
Вопрос:
Прямо сейчас мое приложение выходит из строя, когда коллекция уже существует в Firebase Firestore. Я хочу перехватить эту ошибку, когда она произойдет, но моя текущая реализация ничего не улавливает, поскольку addSnapshotListener()
метод не выдает никаких ошибок.
Текущий код
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()
}
Ошибка после сбоя приложения
Поток 1: «Недопустимая ссылка на коллекцию. Ссылки на коллекции должны иметь нечетное количество сегментов, но иметь 0»
Как я могу перехватить эту ошибку, чтобы я мог отобразить UIAlertController с ошибкой?
Комментарии:
1. Мы не знаем, что
chatName
содержит строка. Можете ли вы включить это в вопрос? Возможно, вы просто захотите добавитьprint(chatName)
прямо перед вызовом firebase, чтобы посмотреть, что это такое. Также используйте только заглавные буквы имен классов и структур . переменные всегда должны быть в нижнем регистре, чтобы избежать путаницы. Поэтому вместоQuery, Error
этого должно бытьquery, error
Ответ №1:
Я бы использовал другой подход.
Чтобы проверить, существует ли коллекция, прочитайте эту коллекцию по имени и определите, есть ли какие-либо документы с помощью snapshot.count равно 0
Проблема здесь в том, что коллекция может содержать большой объем данных, и нет причин читать все это или подключать слушателя, поэтому нам нужно использовать известное поле в этой коллекции, чтобы ограничить результаты.
Я бы предложил функцию с закрытием, которая возвращает true, если коллекция существует, false, если нет, а затем принимает меры на основе этого результата.
Вам понадобится имя коллекции, которую вы хотите протестировать, а затем имя известного поля в этой коллекции для запроса, чтобы ограничить результаты.
Имя поля важно в том смысле, что если коллекция содержит 1 МЛН документов, вы не хотите читать их все — вы просто хотите прочитать один и .OrderBy с ограничением сделает это.
Итак, вот вызывающая функция
func checkCollection() {
self.doesCollectionExist(collectionName: "test_collection", fieldName: "msg", completion: { isEmpty in
if isEmpty == true {
print("collection does not exist")
} else {
print("collection found!")
}
})
}
а затем функция, которая проверяет, существует ли коллекция, путем чтения одного документа и возвращает false, если нет, true, если это так.
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:
Эта ошибка не имеет ничего общего с несуществующей коллекцией Ошибка предполагает, что chatName
это пустая строка, которая является недопустимым параметром. Вместо того, чтобы перехватывать ошибку, вы должны сначала проверить, что chatName
это допустимая строка имени коллекции, прежде чем отправлять ее в Firestore API.
Если вы запрашиваете коллекцию, которая не существует, вы вообще не получите это сообщение об ошибке. Вместо этого вы просто не получите никаких документов в результирующем наборе.
Комментарии:
1.
chatName
однако не пусто, полная строка печатается после добавления инструкции print2. Тогда, что бы это ни было, оно недействительно. Вы должны проверить это, прежде чем передавать его в API. Правила для имен коллекций и документов приведены здесь: firebase.google.com/docs/firestore /…
3. Я пересмотрел вопрос, проблема в том, что коллекция уже существует. В принципе, я хочу проверить, существует ли коллекция. Если это так, я хочу отобразить UIAlertController, но если это не так, я хочу создать коллекцию под этим именем.
4. Вы действительно должны также показать конкретное значение
chatName
, которое работает не так, как вы ожидаете. Нет операции для проверки, существует ли коллекция. Вы должны фактически запросить его и получить из него документ, чтобы узнать, что он существует. Ваш запрос не выполняется, потому что значениеchatName
недопустимо.
Ответ №3:
вы сделаете что-то вроде этого:
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
Комментарии:
1. в этом случае обычно не используйте try catch, вместо этого используйте строку, которую я вам показываю, и она хорошо работает, но это всего лишь рекомендация.