LoginSignup
2
0

More than 1 year has passed since last update.

【非同期処理】UITableViewが`Index out of range`でクラッシュする回避策

Last updated at Posted at 2022-04-02

環境

・Swift 5.5.2
・Xcode 13.2.1

発生したエラー

※一部コードを省略しています

ViewController.Swift
override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  self.users = []
  db.fetchUsers { [weak self] result in
    guard let self = self else { return }
    switch result {
    case .success(let users):
      self.users = users
    case .failure(let error):
      print(error.localizeddescription)
    }     
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell
    cell.configure(user: users[indexPath.row])  //この行で`index out of range`が発生する
    return cell
  }
}

extension ViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("indexpath.row: \(users[indexPath.row])") //タップした時にこの行で`index out of range`が発生する
  }
}

原因

非同期でデータを受け取る前(配列がまだ空)にcellForRowAtdidSelectRowAtが呼ばれて、存在しない要素にアクセスしたため。

回避策

下記のように、配列が空の時は早期リターンでアクセスしないようにすることで回避できます。

ViewController.Swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UITableViewCell
  guard users.count > 0 else { return cell } //このコードを追加
  cell.configure(user: users[indexPath.row])
  return cell
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0