Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在uitableView中删除行时ios应用程序崩溃_Ios_Swift_Uitableview - Fatal编程技术网

在uitableView中删除行时ios应用程序崩溃

在uitableView中删除行时ios应用程序崩溃,ios,swift,uitableview,Ios,Swift,Uitableview,我的UITableView中有一个问题,它填充了数据:[(gamme:String,[(product:String,quantity:Double)]],一切正常:插入行和节,删除行和节,重新加载。 但有时,当我尝试快速删除许多行时(通过在表格中滑动行并点击(-)来逐行删除)。它会导致像截图中那样的崩溃 这个问题很难在开发应用程序中重现。但我的客户仍然报告。我的客户是专业人士(不是普通用户),他们希望能够以快速的方式使用中大型数据 这是我删除行的功能: override func t

我的UITableView中有一个问题,它填充了
数据:[(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]
}