简体   繁体   中英

Swift: Crash when loading a Table many times

I have following issue:

In my App, you have online recipes now imagine a TabViewController. On the first two pages of this TabViewController you have a view displaying recipes stored on the Realtime Database of Firebase. On the third one you have a simple view with some buttons, but no Firebase used and imported. The problem now is, when I slam the Bottom Bar multiple times and therefore switch the TabViewController multiple times in a second the app crashes. This probably because of Firebase reloading everytime since there is a TabViewController change, maybe resulting in a overload.

Now I get following error:

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

It highlights this code let recipe = myRecipes[indexPath.row] with the index out of range. Now how can I either reduce load on the server or avoid this error?

The reason why there is an increased load is probably since I have to fetch multiple recipes from different locations at once like this simplified example:

// 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()
                    }
                }
            }

How could I reduce load? Is there something as multipath udpates in Firebase, but just as a get, so I don't have to load 10-20 recipes with a.observeSingleEvent?

First of all the DispatchQueue block is at the wrong place. It must be inside the closure

GetRecipeService.getRecipe(recipeUID: child.key) { recipe in
   self.myRecipes.append(recipe ?? [String:Any]())
   DispatchQueue.main.async {
      self.tableView.reloadData()
   }
}

To manage multiple asynchronous requests in a loop there is an 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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM