0

Please check in response data delete successfully but not removed from tableview and also when i run again then data not show beacuse its delePelase check here i am deleting on yes button clickHello i am i am deleting rows from tableview and its work fine for me i am successfully removed but after remove i am getting crash and error like below

Error

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

and here i show you my code where i am getting crash

Code

@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()
            }
    }
}

i am not able to understand why i am getting crash can any one please tell me where i am done something wrong

Code For Showing Dialogue

 @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
        }

    }
Vishal Parmar
  • 615
  • 4
  • 31
  • what the result you get from this `buttonPosition` – Anbu.Karthik Jan 18 '19 at 09:43
  • You have lots and lots of force unwraps. Be very careful with those. It makes your app very prone to crashes and failure. Your problem here is that you are for unwrapping the indexPath but it is returning nil. `let indexPath = self.tblOccList.indexPathForRow(at: buttonPosition)!` remove the `!` and `guard` unwrap it or unwrap it conditionally with `if let` – Galo Torres Sevilla Jan 18 '19 at 09:45
  • when i print `buttonPosition` i will get result like this (206.5, -63.0) – Vishal Parmar Jan 18 '19 at 09:46
  • How are you planning to get an indexPath with a tuple? Thats why its crashing. What do you want to achieve here? – emrepun Jan 18 '19 at 09:51
  • i want to delete selected row on button click – Vishal Parmar Jan 18 '19 at 09:52
  • if i use guard and is let then not able to delete rows from tableview – Vishal Parmar Jan 18 '19 at 09:57
  • You are performing UI operations in an asynchronous block too; that isn't a good idea – Paulw11 Jan 18 '19 at 09:57
  • @Paulw11 can you please suggest me another way to solve this – Vishal Parmar Jan 18 '19 at 10:02
  • What is the context for the code shown? Is it in the tableview or in the cell? You have lots of force unwraps - that is bad. You seem to be using user defaults for storing part of your data model - that is bad. You should handle the button tap in your cell and have it notify the tableview of the tap via a delegation pattern. You should immediately delete the item from your local array and delete the row from your tableview and then dispatch the network update to complete in the background – Paulw11 Jan 18 '19 at 10:05
  • @VishalParmar Check my answer – Abhishek Jadhav Jan 18 '19 at 10:16
  • It is not very robust to use the position on screen to recompute the indexPath. Should better attach a tag to each cell and use it to build the indexPath. – claude31 Jan 18 '19 at 12:37

2 Answers2

2

You can define a property to save the selected indexPath before pop up the dialogue.

var selectedIndexPath: IndexPath?

And change this

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

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

To

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

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

Then try changing this

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

to

guard let indexPath = self.selectedIndexPath else { return }
ZHZ
  • 2,088
  • 13
  • 16
0

Add in tableview cellForRowAt delegate method assign button tag to 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()
            }
    }
}
Abhishek Jadhav
  • 706
  • 5
  • 12