Swift: сбой при многократной загрузке таблицы
У меня следующая проблема:
В моем приложении у вас есть онлайн-рецепты, теперь представьте себе TabViewController. На первых двух страницах этого TabViewController у вас есть представление, отображающее рецепты, хранящиеся в базе данных в реальном времени Firebase. На третьем у вас есть простой вид с некоторыми кнопками, но Firebase не используется и не импортируется. Проблема теперь в том, что когда я несколько раз хлопаю по нижней панели и, следовательно, переключаю TabViewController несколько раз за секунду, приложение вылетает. Вероятно, это из-за того, что Firebase перезагружается каждый раз, так как происходит изменение TabViewController, что может привести к перегрузке.
Теперь я получаю следующую ошибку:
Fatal error: Index out of range: file /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift, line 444
2020-05-22 16:44:28.057640+0200 GestureCook[10451:3103426] Fatal error: Index out of range: file /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift, line 444
Он выделяет этот код let recipe = myRecipes[indexPath.row]
с индексом вне допустимого диапазона. Как теперь уменьшить нагрузку на сервер или избежать этой ошибки?
Причина увеличения нагрузки, вероятно, связана с тем, что мне нужно получить несколько рецептов из разных мест одновременно, как в этом упрощенном примере:
// dict is a list of recipe IDs
// And the GetRecipeService.getRecipe is a service which gets a recipe using a .observeSingleEvent (this causes these requests)
for child in dict {
GetRecipeService.getRecipe(recipeUID: child.key) { recipe in
self.myRecipes.append(recipe ?? [String:Any]())
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
Как уменьшить нагрузку? Есть ли что-то вроде многопутевого обновления в Firebase, но просто как получить, чтобы мне не нужно было загружать 10-20 рецептов с помощью.observeSingleEvent?
1 ответ
Прежде всего DispatchQueue
блок находится не в том месте. Он должен быть внутри крышки
GetRecipeService.getRecipe(recipeUID: child.key) { recipe in
self.myRecipes.append(recipe ?? [String:Any]())
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Для управления несколькими асинхронными запросами в цикле существует API: DispatchGroup
let group = DispatchGroup()
for child in dict {
group.enter()
GetRecipeService.getRecipe(recipeUID: child.key) { recipe in
self.myRecipes.append(recipe ?? [String:Any]())
group.leave()
}
}
group.notify(queue: .main) {
self.tableView.reloadData()
}