UITableView:IndexPath.row 超出范围(致命错误)

Posted

技术标签:

【中文标题】UITableView:IndexPath.row 超出范围(致命错误)【英文标题】:UITableView: IndexPath.row out of range (FATAL ERROR) 【发布时间】:2018-02-15 08:29:05 【问题描述】:

我有一个表格视图,列出了与游戏相关的人员。当一个玩家被淘汰时,我运行以下代码:

func doRemovePlayer(playerDed: GKPlayer) 

    print("\n ** Removing \(playerDed.alias!) from the game! ** \n")
    gameLog += "Removing \(playerDed.alias!) from the game!"
    let elIndex = (gKPlayerArray.index(of: playerDed))!
    scoreArray.remove(at: elIndex)
    randomNoArray.remove(at: elIndex)
    timeResultsArray.remove(at: elIndex)
    answerResultArray.remove(at: elIndex)
    playersReadyForNextStage.remove(at: elIndex)
    gKPlayerArray.remove(at: elIndex)
    noOfPlayers -= 1
    print ("New Array counts are: \(scoreArray.count), \(randomNoArray.count), \(timeResultsArray.count), \(answerResultArray.count), \(playersReadyForNextStage.count), \(gKPlayerArray.count), Players: \(noOfPlayers)")
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01, execute: 
        self.scoreBoardTable.reloadData()
    )
    checkIfWinnerOrLoser()

如您所见,我做了一个调度队列只是为了避免任何问题(我认为)。 无论如何,当我在 2 个模拟器和我的实际 iPhone 上运行此代码时,模拟器对此代码没有问题,但是 iPhone 3/4 次给了我一个 FATAL ERROR: INDEX OUT OF RANGE 并指向此特定行在代码中:

extension GameScreenVC: UITableViewDelegate, UITableViewDataSource 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return gKPlayerArray.count
    

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let scoreCell = tableView.dequeueReusableCell(withIdentifier: "playerCell") as! ScoreBoardTableCell
    **scoreCell.nameLabel.text = gKPlayerArray[indexPath.row].alias!** //FATAL ERROR: INDEX OUT OF RANGE
    scoreCell.scoreLabel.text = String(scoreArray[indexPath.row])
    if indexPath.row == 0 
        scoreCell.layer.borderWidth = 3
        scoreCell.layer.borderColor = UIColor.blue.cgColor
     else 
        scoreCell.layer.borderWidth = 0
    
    scoreCell.statusLabel.layer.cornerRadius = 7
    if playersReadyForNextStage[indexPath.row] 
        scoreCell.statusLabel.layer.backgroundColor = UIColor.yellow.cgColor
     else 
        scoreCell.statusLabel.layer.backgroundColor = UIColor.green.cgColor
    
    return scoreCell

我不确定如何解决这个问题。我会“打印”所有数组的新值以防万一,并且我确实确认它们都是正确的(它们是 3 现在它们是 2)。然后,当它运行表的更新时,它会崩溃,认为 indexPath.row 中有第三个元素? (我认为这就是正在发生的事情)。 IndexPath.row 像没有更新还是什么?有没有办法更正确地更新它?

【问题讨论】:

你能发布你的numberOfRow方法吗? 哦!!是的对不起。会发的 doRemovePlayer 在与 main 不同的线程上调用的吗? 我打印 gKPlayerArray.count 是正确的 会不会导致 iPhone 崩溃的刷新不是由您拨打 reloadData 引起的? 【参考方案1】:

如果doRemovePlayer 在主线程上被调用,你没有理由稍后调度重载。试试这个:

func doRemovePlayer(playerDed: GKPlayer) 

    print("\n ** Removing \(playerDed.alias!) from the game! ** \n")
    gameLog += "Removing \(playerDed.alias!) from the game!"
    let elIndex = (gKPlayerArray.index(of: playerDed))!
    scoreArray.remove(at: elIndex)
    randomNoArray.remove(at: elIndex)
    timeResultsArray.remove(at: elIndex)
    answerResultArray.remove(at: elIndex)
    playersReadyForNextStage.remove(at: elIndex)
    gKPlayerArray.remove(at: elIndex)
    noOfPlayers -= 1
    print ("New Array counts are: \(scoreArray.count), \(randomNoArray.count), \(timeResultsArray.count), \(answerResultArray.count), \(playersReadyForNextStage.count), \(gKPlayerArray.count), Players: \(noOfPlayers)")
    // it should be enough to delete the corresponding row
    scoreBoardTable.deleteRows(at: [IndexPath(row: elIndex, section: 0)], with: .automatic)
    checkIfWinnerOrLoser()

【讨论】:

我认为 removePlayers 不在主线程中。我做了一个dispatch queue.main.async gKPlayerArray.remove(at:elIndex) (因为它是负责设置行数的数组)。它现在似乎正在工作(到目前为止 3/3 没有崩溃) @dvd.Void 你认为?伙计,代码是准确的,你也必须准确.. doRemovePlayer 在哪里调用? 您可以通过print("On main thread:", Thread.isMainThread)查看... 好的,我测试过了。它在主线程上运行。那么我应该删除所有调度队列吗? (但请注意,过去我没有它们并且我有崩溃。现在我添加它们没有崩溃) @dvd.Void 当然.. 如果没有必要,用调度调用将代码弄乱是没有意义的.. 你应该没问题,我们只是我的代码.. 除非有其他问题

以上是关于UITableView:IndexPath.row 超出范围(致命错误)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UITableView 中获取选定的 indexPath.section 和 indexPath.row 值?

UITableView 的 indexPathForCell:总是返回 0 作为 indexPath.row

在 xcode 8 beta 6 的 UITableView 中使用 indexPath.row 将无法编译

UITableView / indexPath.row:为什么if语句排除第10行?

如何“重置”下一个 indexPath.row 成为当前 indexPath.row?

UITableView 中的 indexPath 和 indexPath.section