从 tableview 删除行时崩溃

Posted

技术标签:

【中文标题】从 tableview 删除行时崩溃【英文标题】:crash while deleting rows from tableview 【发布时间】:2019-01-18 09:42:10 【问题描述】:

错误

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

在这里,我向您展示我的代码崩溃的地方

代码

@IBAction func btnDeleteYesTapped(_ sender: UIButton) 
    let preferences = UserDefaults.standard
    let uid = "u_id"
    let acTkn = "acc_tkn"

    let u_ID = preferences.object(forKey: uid)
    let A_Token = preferences.object(forKey: acTkn)

    let params = ["user_id": u_ID!, "access_token": A_Token!,"property_id": propertyID!,"occupants_id": oCCID!]
    print(params)
    Alamofire.request(propertyoccupantsdelete, method: .post, parameters: params).responseJSON
        
            response in
            print(response)
            let result = response.result.value
            print(response)
            let data = result as! [String : AnyObject]
            let status = data["success"] as! String
            if status == "1"
                let buttonPosition : CGPoint = (sender as AnyObject).convert((sender as AnyObject).bounds.origin, to: self.tblOccList)
                let indexPath = self.tblOccList.indexPathForRow(at: buttonPosition)! //At Here I am Getting crash 
                self.occuPantsData.remove(at: indexPath.row)
                self.tblOccList.deleteRows(at: [indexPath], with: .fade)
                Toast(text: data["message"] as? String).show()
            else
              Toast(text: data["message"] as? String).show()
            
    

我不明白为什么我会崩溃,谁能告诉我我做错了什么

显示对话的代码

 @objc func handleLongPress(longPressGesture:UILongPressGestureRecognizer) 

        let p = longPressGesture.location(in: self.tblOccList)
        let indexPath = self.tblOccList.indexPathForRow(at: p)

        if indexPath == nil 
            print("Long press on table view, not row.")
        
        else if (longPressGesture.state == UIGestureRecognizer.State.began) 
            print("Long press on row, at \(indexPath!.row)")
            let id = occuPantsData[indexPath!.row].id
            print(id)
            self.oCCID = id
            self.viewDeletePopUp.isHidden = false
        

    

【问题讨论】:

你从这个buttonPosition得到什么结果 你有很多很多的力量展开。对这些要非常小心。它使您的应用程序很容易崩溃和失败。您的问题是您要解开 indexPath 但它返回 nil。 let indexPath = self.tblOccList.indexPathForRow(at: buttonPosition)! 删除 !guard 解包或使用 if let 有条件地解包 当我打印 buttonPosition 我会得到这样的结果 (206.5, -63.0) 您打算如何获取带有元组的 indexPath?这就是它崩溃的原因。您想在这里实现什么目标? 我想在点击按钮时删除选中的行 【参考方案1】:

您可以在弹出对话框之前定义一个属性来保存选定的 indexPath。

var selectedIndexPath: IndexPath?

然后改变这个

let indexPath = self.tblOccList.indexPathForRow(at: p)

        if indexPath == nil 
            print("Long press on table view, not row.")
        

self.selectedIndexPath = self.tblOccList.indexPathForRow(at: p)

        if self.indexPath == nil 
            print("Long press on table view, not row.")
        

然后尝试改变这个

let indexPath = self.tblOccList.indexPathForRow(at: buttonPosition)!

guard let indexPath = self.selectedIndexPath else  return 

【讨论】:

如果我用你的代码替换我会收到错误,就像这个Cannot convert value of type 'PropertyDetailViewController' to expected argument type 'UITableViewCell' 我在 tableview 单元格长按上显示弹出窗口,然后我删除该行,如果他们有可能发生这种崩溃 没有弹出窗口上的删除按钮意味着长按单元格我显示弹出确认删除,然后按是按钮我正在删除 更新了答案。希望有所帮助 请检查图像我得到了成功响应,但仍然没有从 tableview 中删除行,当我再次运行时,数据不会出现,因为它已删除【参考方案2】:

在tableview中添加cellForRowAt委托方法将按钮标签分配给indexPath.row

     cell.button.tag = indexPath.row 

    @IBAction func btnDeleteYesTapped(sender: UIButton) 
    let preferences = UserDefaults.standard
    let uid = "u_id"
    let acTkn = "acc_tkn"

    let u_ID = preferences.object(forKey: uid)
    let A_Token = preferences.object(forKey: acTkn)

    let params = ["user_id": u_ID!, "access_token": A_Token!,"property_id": propertyID!,"occupants_id": oCCID!]
    print(params)
    Alamofire.request(propertyoccupantsdelete, method: .post, parameters: params).responseJSON
        
            response in
            print(response)
            let result = response.result.value
            print(response)
            let data = result as! [String : AnyObject]
            let status = data["success"] as! String
            if status == "1"                
                let indexPath = IndexPath(row: sender.tag, section: 0)
                self.occuPantsData.remove(at: indexPath.row)
                self.tblOccList.reloadData()
                Toast(text: data["message"] as? String).show()
            else
              Toast(text: data["message"] as? String).show()
            
    

【讨论】:

这不起作用它让我在我得到的地方崩溃 不,您可以只检查成功后必须添加的两行并将 indexPath.row 分配给 button.tag

以上是关于从 tableview 删除行时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

删除行后更新 indexPath 值

在 tableview 中返回 1 行时应用程序崩溃

如何在 C# 中删除 TableView 中的行时从右到左单元格设置动画

iOS Swift 2 - 删除 tableView 行时出错

UITableView 和 numberOfRowsInSection 崩溃

从 tableview 部分删除最后一行时,iOS 应用程序崩溃