在uitableView中删除行时ios应用程序崩溃
我的UITableView中有一个问题,它填充了在uitableView中删除行时ios应用程序崩溃,ios,swift,uitableview,Ios,Swift,Uitableview,我的UITableView中有一个问题,它填充了数据:[(gamme:String,[(product:String,quantity:Double)]],一切正常:插入行和节,删除行和节,重新加载。 但有时,当我尝试快速删除许多行时(通过在表格中滑动行并点击(-)来逐行删除)。它会导致像截图中那样的崩溃 这个问题很难在开发应用程序中重现。但我的客户仍然报告。我的客户是专业人士(不是普通用户),他们希望能够以快速的方式使用中大型数据 这是我删除行的功能: override func t
数据:[(gamme:String,[(product:String,quantity:Double)]]
,一切正常:插入行和节,删除行和节,重新加载。
但有时,当我尝试快速删除许多行时(通过在表格中滑动行并点击(-)来逐行删除)。它会导致像截图中那样的崩溃
这个问题很难在开发应用程序中重现。但我的客户仍然报告。我的客户是专业人士(不是普通用户),他们希望能够以快速的方式使用中大型数据
这是我删除行的功能:
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "-") { (action, indexPath) in
let cmd = self.groupedData[indexPath.section].1.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .right)
self.delegate?.didDeleteCmdLine(cmd)
if self.groupedData[indexPath.section].1.count == 0 {
self.groupedData.remove(at: indexPath.section)
tableView.deleteSections(IndexSet(integer: indexPath.section), with: UITableViewRowAnimation.right)
}
}
return [delete]
}
为什么会这样
这是用于崩溃的xcode Organizer屏幕
编辑:
检查@Reinhard建议的除main之外的任何线程是否访问了groupedData
:
private var xgroupedData = [(gamme: GammePrdCnsPrcpl, [cmdline])]()
private var groupedData: [(gamme: GammePrdCnsPrcpl, [cmdline])] {
get {
if !Thread.isMainThread {
fatalError("getting from not from main")
}
return xgroupedData
}
set {
if !Thread.isMainThread {
fatalError("setting from not from main")
}
xgroupedData = newValue
}
}
但是
groupedData
变量只能从主线程访问请尝试像此函数一样使用
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
// do your delete your entires here..
//
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
若昂·路易斯·费尔南德斯的变化回答了……试试这个
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
objects.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
参考(使用swift进行黑客攻击)。你可以试试这个
var myDataArray = ["one","two","three"]
//wanna insert a row then in button action or any action write
myDataArray.append("four")
self.tblView.reloadData()
// wanna delete a row
myDataArray.removeObject("two")
// you can remove data at any specific index liek
//myDataArray.remove(at: 2)
self.tblView.reloadData()
用户点击“删除”按钮后,从数据源
groupedData
(一个数组)中删除相应的行和(如果这是该节的最后一行)相应的节。但是,数组操作不是线程安全的当删除操作修改该数组时,是否有另一个线程正在使用该数组? 在这种情况下,应用程序可能会崩溃。当然,在短时间内触发多个动作时,危险更大,正如您所描述的那样。
避免多线程问题的一种方法(可能不是最好的)是只在主线程上访问数组。
如果这减慢了主线程的速度,可以使用同步阵列,允许同时进行多个读取,但只有一次写入会阻止所有读取,请参阅。只有更新@codebythes的答案
删除特定行时,请更新数据源文件
tableView.beginUpdates()
self.whatEverDataSource.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
这将导致数据源与TableView同时更新。发生崩溃的原因可能是数据源未更新 在删除节中的最后一项时,是否可以尝试一次删除节,而不是一次删除行,然后删除它所属的节
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "-") { [weak self] (action, indexPath) in
// Use a weak reference to self to avoid any reference cycles.
guard let weakSelf = self else {
return
}
tableView.beginUpdates()
let cmd: cmdline
if weakSelf.groupedData[indexPath.section].1.count > 1 {
cmd = weakSelf.groupedData[indexPath.section].1.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .right)
} else {
// Remove the section when the `items` are empty or when the last item is to be removed.
cmd = weakSelf.groupedData.remove(at: indexPath.section).1[indexPath.row]
tableView.deleteSections([indexPath.section], with: .right)
}
weakSelf.delegate?.didDeleteCmdLine(cmd)
tableView.endUpdates()
}
return [delete]
}
为什么要删除整个部分?如果该部分(gamme)没有更多产品,则必须将其删除too@brahimm这是你应用程序生产版本的真实屏幕截图吗?如果是这样的话,您可能希望去掉其中的API键@dnlggr谢谢你,但不是说这只是为了devI,我想可能是你在把索引路径复制到行操作闭包中。请尝试将模型对象复制到块中,然后重新计算要在闭包内部删除的节索引。您好,谢谢您的回复,但问题仍然存在。在您将tableview设置为
isEditing=true
之前,此函数不会提供滑动选项,因此您想通过滑动来删除行吗?是的。看起来下面的答案对我有用。谢谢你是的,另一个答案可能对你很好。(Y) 嗨,谢谢你的重播。不知怎的,这起作用了!!您能否解释一下,当您重新加载所有tableview时,有时会出现错误,因为可恢复单元格。这可能是由于几个原因(数据计数、零值等)。但现在你只需要重新加载特定的单元格。如果这是您的真实答案,请标记为已接受。问题仍然存在!如果我尝试快速删除,也会以同样的方式崩溃。还有其他想法吗?当删除操作运行时,您是否尝试冻结tableview滚动?您的意思是什么?不,我没有对这件事做任何事scroll@zgue这个解决方案有什么问题。。?。。请解释我只在审核队列中编辑了您的答案。否决票来自其他人。@RajanSingh我尝试过,但有时仍会崩溃。屏幕截图是我的问题。您好,感谢重播,在向数据添加值时,您实际上应该执行tblView.insertRow(indexPath)
。因为reloadData()
将刷新所有不可用的tableViewnecessary@brahimm然后在indexpath中使用tblview.reloadrows重新加载您最近的行,那么您的所有数据都不会重新加载,谢谢您的重播。我尝试了您的建议(请参见编辑的问题),但我发现grroupedData只能由主线程访问。因此,如果您仅从主线程访问阵列,我的回答不适用,抱歉。您好,感谢重播。这实际上是我已经在使用的实现。我的意思是,这是我正在使用的实现,并且崩溃了。
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "-") { [weak self] (action, indexPath) in
// Use a weak reference to self to avoid any reference cycles.
guard let weakSelf = self else {
return
}
tableView.beginUpdates()
let cmd: cmdline
if weakSelf.groupedData[indexPath.section].1.count > 1 {
cmd = weakSelf.groupedData[indexPath.section].1.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .right)
} else {
// Remove the section when the `items` are empty or when the last item is to be removed.
cmd = weakSelf.groupedData.remove(at: indexPath.section).1[indexPath.row]
tableView.deleteSections([indexPath.section], with: .right)
}
weakSelf.delegate?.didDeleteCmdLine(cmd)
tableView.endUpdates()
}
return [delete]
}