Search code examples
iosswiftuitableviewdelete-row

How to delete a cell in a section using custom action?


ive been struggling too delete my cells in the tableview using trailingSwipeActionsConfigurationForRowAt I have it set up to where you swipe the cell the delete image shows up and an alertView shows when the delete image is pressed and asks if you want to delete the row. But once yes is pressed the cell doesn't get deleted/removed

import UIKit

class CartViewController: UIViewController {

    var selectedProduct: ItemList!       // allows data to be passed into the CartVC

    // allows data to be sepearted into sections
    var cartItems: [CartItem] = []
    var groupedItems: [String: [CartItem]] = [:]
    var brandTitle: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        groupedItems = Dictionary(grouping: cartItems, by: {$0.itemList.brandName})
        brandTitle = groupedItems.map{$0.key}.sorted()
    }
}

extension CartViewController: UITableViewDelegate, UITableViewDataSource{

    func numberOfSections(in tableView: UITableView) -> Int {
        return brandTitle.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let brand = brandTitle[section]
        return groupedItems[brand]!.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cartCell = tableView.dequeueReusableCell(withIdentifier: "CartCell") as! CartCell

        let brand = brandTitle[indexPath.section]
        let itemsToDisplay = groupedItems[brand]![indexPath.row]
        cartCell.configure(withCartItems: itemsToDisplay.productList)

        return cartCell
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cartHeader = tableView.dequeueReusableCell(withIdentifier: "CartHeader") as! CartHeader

        let headerTitle = brandTitle[section]
        cartHeader.brandName.text = "Brand: \(headerTitle)"

        return cartHeader
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 45
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let cartFooter = tableView.dequeueReusableCell(withIdentifier: "CartFooter") as! CartFooter

        let brand = brandTitle[section]
        let subtotal = groupedItems[brand]?.map { $0.getCartTotal() }.reduce(0, +) ?? 0
        cartFooter.cartTotal.text = String(subtotal)

        return cartFooter
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 150
    }

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let edit = UIContextualAction(style: .normal, title: "") { (action, view, nil) in
            let refreshAlert = UIAlertController(title: "Deletion", message: "Are you sure you want to remove this item from cart? ", preferredStyle: .alert)

            refreshAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action: UIAlertAction!) in

            }))

            refreshAlert.addAction(UIAlertAction(title: "No", style: .default, handler: { (action: UIAlertAction!) in
                refreshAlert .dismiss(animated: true, completion: nil)
            }))

            self.present(refreshAlert, animated: true, completion: nil)
        }
        edit.backgroundColor = .red
        edit.image = #imageLiteral(resourceName: "best_sellers")
        let config = UISwipeActionsConfiguration(actions: [edit])
        config.performsFirstActionWithFullSwipe = false
        return config
    }
}

Solution

  • iOS checks the number of rows before and after a delete operation, and expects them to add up correctly following the change.In your alert action you need to delete your current object.

    refreshAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action: UIAlertAction!) in
                 tableView.beginUpdates()
                 // brandTitle[indexPath.section].remove(at: indexPath.row) // or you can directly use this
    
                  let brand = brandTitle[indexPath.section]                                        
                     groupedItems[brand]!.remove(at:indexPath.row)
                       tableView.deleteRows(at: [indexPath], with: .fade)
                       tableView.endUpdates()
             }))