Search code examples
iosswiftuitableviewdelegatesprotocols

TableViewCell delegation with Swift


I have ViewController (MainVC) with TableView filled with custom cells. They have enabled or disabled star sign.

enter image description here

When user taps on cell he navigates to separate ViewController (DetailedVC). There is button there which switches featured status for the object. I want to use delegation pattern for this case - so when user comes back to MainVC object featured status is also updated.

I created protocol

protocol FeaturedDelegate {
   func toggleFeatured (cell : CustomCell) 
}

Made MainVC conform to it

class MainVC : UIViewController, UITableViewDelegate, UITableViewDataSource, FeaturedDelegate {
     func toggleFeatured (cell : CustomCell) {
        //toggle featured status for cell
     }
}
......
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: CustomCell = ...
    cell.featuredDelegate = self
    return cell
}

In this case the delegate is inside cell. But I need ti to be in DetailedVC. What should I do next?


Solution

  • Create a protocol in DetailVC.

    //DetailVC

    protocol SecondViewControllerDelegate: class {
        func toggleFeatured (indexOfCell index: Int, isEnable: Bool)
    }
    

    When star value is change than call this delegate function.

    delegate?.toggleFeatured(indexOfCell: indexOfCell, isEnable: isEnable)
    

    In Masterviewcontroller's tableview didselected function set delegate

    //MasterViewController

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let detailVC = DetailVC()/* get detalVC object */
    
        detailVC.delgate = self
        detailVC.indexOfCell = indexPath.row
    
        //show detailvc
    }
    

    If you don't want to reload complete tableview then you can reload cell only.

    extension MasterViewController: SecondViewControllerDelegate {
       func toggleFeatured(indexOfCell index: Int, isEnable: Bool) { 
    
       let object = array[index]
       // Logic to enable or disable star for for object
    
        tableView.reloadRows(at: [IndexPath(item: index, section: 0)], with: .automatic)
       }
    }
    

    MOST IMPORTANT

    Don't forgot to make the delegate weak. weak keyword won't let the retain count increase by one hence retain cycle don't generate and memory leak problems won't come. if we don't write and any keyword then it will be strong by default which increase the retain count and create retain cycle(Deadlock).

    And We need to make protocol class type because weak keyword can be use only with class type protocol. check protocol declaration, it inherited class

    class DetailVC {
       weak delegate: SecondViewControllerDelegate?
    }
    

    Check out this video to understand memory leak and fix it.

    https://www.youtube.com/watch?v=sp8qEMY9X6Q