从 UITableView 中删除值会导致崩溃

Posted

技术标签:

【中文标题】从 UITableView 中删除值会导致崩溃【英文标题】:Removing value from UITableView causes crash 【发布时间】:2018-01-01 15:24:54 【问题描述】:

我有一个 UITableView,当我点击一个单元格时,我将 firebase 中的一个值更新为 true。我还实现了删除 UITableViewCell 的功能。问题是,如果单击(更新)单元格然后删除应用程序崩溃。当我查看 firebase 时,已更新的值尚未被删除(其他所有内容都已删除),只有在单元格已更新时才会发生这种情况。这就是我得到的

// remove task

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 

    let taskToDelete = groupTask[indexPath.row]

    if editingStyle == UITableViewCellEditingStyle.delete 
        groupTask.remove(at: indexPath.row)
        DataService.instance.REF_GROUPS.child(group!.key).child("task").child(taskToDelete.id).removeValue(completionBlock:  (error, refer) in
            if error != nil 

             else 

            
        )
        self.tableView.reloadData()
    


// update task value

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    guard let cell = tableView.cellForRow(at: indexPath) as? GroupTaskCell else  return 

    if cell.isSelected == true 
        let selected = groupTask[indexPath.row]
        DataService.instance.REF_GROUPS.observe(.value)  (snapShot) in
            DataService.instance.updateTaskStatus(desiredGroup: self.group!, selected: true, atIndexpath: indexPath.row, childPath: selected.id, handler:  (complete) in
                self.tableView.reloadData()
            )
        
     else 

    
    self.tableView.reloadData()



// update task status

func updateTaskStatus(desiredGroup: Group, selected: Bool, atIndexpath: Int, childPath: String, handler: @escaping (_ taskArray: [Task]) -> ()) 

    REF_GROUPS.child(desiredGroup.key).child("task").child(childPath).updateChildValues(["selected": selected])
    

编辑!

无法将“NSNull”(0x1b5915f18) 类型的值转换为“NSString”(0x1b5921ad8)。 2018-01-01 17:38:53.431901+0200 WireUp[587:103199] 无法将“NSNull”(0x1b5915f18)类型的值转换为“NSString”(0x1b5921ad8)。 (lldb)

在我删除任务之前,firebase 的样子:

之后:

如您所见,它并未删除已更新的值,而这正是导致崩溃的原因。感谢所有帮助。

func addTask(withTask task: String, andPeople people: String, forUID uid: String, withGroupKey groupKey: String?, selectedStatus selected: Bool, sendComplete: @escaping (_ taskCreated: Bool ) -> ()) 
    if groupKey != nil 
        REF_GROUPS.child(groupKey!).child("task").childByAutoId().updateChildValues(["taskToDo": task, "peopleToDoTask": people, "senderId": uid, "selected": selected])
        sendComplete(true)
     else 

    


func updateTaskStatus(desiredGroup: Group, selected: Bool, childPath: String, handler: @escaping (_ taskArray: [Task]) -> ()) 

    REF_GROUPS.child(desiredGroup.key).child("task").child(childPath).updateChildValues(["selected": selected])
    


func configureTaskCell(taskToDo task: String, nameForPerson name: String, isSelected: Bool ) 
    self.task.text = task
    self.name.text = name
    if isSelected 
        self.chechImg.isHidden = false
     else 
        self.chechImg.isHidden = true
    

【问题讨论】:

能否显示崩溃结果。 . ? 我把崩溃结果放在上面 我认为您对 cellForRowAtIndexPath: data source 方法有问题,您将 null 值分配给受限字符串。 . .我建议您在所有异常上添加断点,这将指向问题所在的确切行。 【参考方案1】:

尝试使用 UITableView 的 beginUpdate()endUpdate() 方法更新和删除单元格,而不是在表视图委托函数中使用 self.tableView.reloadData()。您不会崩溃,也不会重新加载整个表。在 Obj-C 中,删除和更新单元格看起来像这样:

[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];

[tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects: indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];

【讨论】:

这会正确删除所有内容,但由于某种原因,它会在 firebase 中创建一个新子项,并传入 "selected": true 并且应用程序崩溃。好像有别的问题 首先begin- / endUpdates 毫无意义——甚至在reloadRowsAtIndexPaths 前后都没有任何作用——其次reloadRowsAtIndexPaths 是多余的,因为deleteRowsAtIndexPaths 已经更新了UI。【参考方案2】:

您提供的代码似乎不是问题。它被正确删除,但当您删除它时,它也会再次更新,仅使用 selected: true。在您的代码中的某处,它将尝试获取其余数据,包括 selected: true 但它不存在;导致崩溃。您可能需要进行一些调试,以查看您实际将此选定值更新到数据库的位置并删除它

【讨论】:

问题是它没有从firebase中删除值,然后导致崩溃 是的,我知道为什么会崩溃(它找不到数据),但不知道为什么 selected: true 再次更新。你有什么解决办法吗? @Oscar 我会亲自前往 Xcode 的搜索栏(在左侧 - 点击 cmd + 3)并搜索“selected”或“selected”:true。这将从字面上显示您正在调用它的任何地方,以帮助您找到删除后可以调用它的位置。我还会在每一行上放置一个断点,以准确了解它是否被调用,因为当您删除某些内容时它会到达该断点。 我已经通过代码,找不到问题。如果你能找到什么问题,你能看透它吗?将不胜感激。我把代码放在@daniel上面

以上是关于从 UITableView 中删除值会导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

UITableView删除cell导致崩溃的bug

如何防止多次快速点击 UITableView 的编辑按钮导致应用程序崩溃?

在后台删除的数据导致 UITableView 中的索引超出范围崩溃

UITableView删除行到最后一条时崩溃

在uitableview单元格上留下滑动删除按钮打开然后返回导致崩溃

从 UItableview 删除一行时崩溃