【问题标题】:Array indexing not updating after deleting one element删除一个元素后数组索引不更新
【发布时间】:2019-11-12 12:14:53
【问题描述】:

从 tableStoryArray[] 中删除一个元素后,下一个元素索引不会更改或更新,因为当我尝试删除下一个元素时,它会因“索引超出范围”而崩溃。

   @IBAction func Btn4Action(_ sender: Any) { // Delete row

        self.tableStoryArray.remove(at: index!.row)
        self.tableView.beginUpdates()
        self.tableView.deleteRows(at: [index!], with: .middle)
        self.tableView.endUpdates()
        self.tableView.reloadData()


  }

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? WriteStoryTableViewCell

        cell?.charNameinStory.text =  self.tableStoryArray[indexPath.row]["charName"] as? String
        cell?.charNameinStory.textColor =  self.tableStoryArray[indexPath.row]["charNameColor"] as? UIColor
        cell?.cellView.backgroundColor =  self.tableStoryArray[indexPath.row]["backgroundcolor"] as? UIColor
        cell?.charImageinStory.image = self.tableStoryArray[indexPath.row]["image"] as? UIImage
        cell?.charRelationinStory.text = self.tableStoryArray[indexPath.row]["charRelation"] as? String
        cell?.textView.text = self.tableStoryArray[indexPath.row]["story"] as? String

        if self.tableStoryArray[indexPath.row]["charName"] as? String != "" {
            cell?.charetailViewHeightConstraint.constant = 38
            cell?.chardetailViewinStory.isHidden = false

        }else{
            cell?.charetailViewHeightConstraint.constant = 0
            cell?.chardetailViewinStory.isHidden = true

        }

        return cell

}

致命错误:索引超出范围

【问题讨论】:

  • 从哪里获得索引?您现在遇到的错误是因为数组或 tableview 的行上不存在该错误。您需要先找到索引。好吧,您可以从发件人对象(您的按钮对象)中找到它。找到索引后,您可以检查索引是否存在于数组中。
  • if self.tableStoryArray.indices.contains(index!.row) { //.. 你删除东西的逻辑。并且也不要重新加载 tableview,因为您已经从 tableview 的行中删除了对象表单数组源。
  • 我在单元格内使用 textView 的标签作为 index = IndexPath(row: textView.tag, section: 0)
  • 你不需要在 Cell 中使用 textView.tag,我的意思是你可能通过 indexPath.row 分配了 textView 的第一个标签值。在这种情况下,您可以直接使用 indexPath.row 的值。你能告诉我你在 cellForRow 里面做的代码吗?
  • 但在代码中,您没有将任何值分配给 textView.tag。只需按照我的建议表进行第一条和第二条评论即可。

标签: ios arrays swift indexing


【解决方案1】:

在这种情况下更新所有单元格的标签不要删除带有deleteRows的行而是重新加载整个表格视图

@IBAction func Btn4Action(_ sender: Any) { // Delete row
    self.tableStoryArray.remove(at: index!.row)
    self.tableView.reloadData()
}

并且您必须在cellForRow 中分配标签。

顺便强制解开单元格。此时的崩溃揭示了可以立即修复的设计错误。并且不要一次又一次地获取相同的对象,这不必要地昂贵(自定义结构会更有效)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! WriteStoryTableViewCell
   cell.textView.tag = indexPath.row // crucial !!
   let story = self.tableStoryArray[indexPath.row]
   cell.charNameinStory.text =  story["charName"] as? String
   cell.charNameinStory.textColor = story["charNameColor"] as? UIColor     
   ...

【讨论】:

    【解决方案2】:

    首先,在cellForRowIndexPath方法中设置UIButton的标签

    Btn4Action.tag = indexPath.row 
    

    带有特定按钮标记的第二个删除行。

    @IBAction func Btn4Action(_ sender: UIButton) { // Delete row
    
                            if self.tableStoryArray.indices.contains(sender.tag) {
    
                                self.tableStoryArray.remove(at: sender.tag)
                                self.tableView.beginUpdates()
                                self.tableView.deleteRows(at: [sender.tag], with: .middle)
                                self.tableView.endUpdates()
                            }
                        }
    

    【讨论】:

    • 我在单元格内使用 textView 的标签作为 index = IndexPath(row: textView.tag, section: 0)