从 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 的编辑按钮导致应用程序崩溃?
在后台删除的数据导致 UITableView 中的索引超出范围崩溃