Search code examples
swiftdelegatesretain-cycle

Should I make delegate of custom cell as a weakly referenced proprety?


ViewController Code

class ViewController: UIViewController {
    deinit {
        print("ViewController deinitialised")
    }

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        self.tableView.dataSource = self
    }

    func didTapBlue() {

    }
}

extension ViewController: UITableViewDataSource, CustomCellDelegate {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("myCell") as! CustomCell
        cell.delegate =  self
        cell.textLabel!.text = "\(indexPath.row)"
        return cell
    }

    func buttonTapped() {
        print("Button tapped")
    }
}

CustomCell Code

class CustomCell: UITableViewCell {
    deinit {
        print("Cell deinitialised")
    }

    var delegate: CustomCellDelegate! //When protocol Type is A
    // weak prefix when protocol Type is B
    // weak var delegate: CustomCellDelegate!

    @IBAction func buttonClickAction(sender: AnyObject) {
        if let del = self.delegate {
            del.buttonTapped()
        }
    }
}

Protocol Type A

protocol CustomCellDelegate{
    func buttonTapped()
}

Protocol Type B

protocol CustomCellDelegate: class {
    func buttonTapped()
}

I am confused about what is the appropriate way to implement delegate pattern for passing message between Cell And ViewController. I know that if two objects hold each other's reference strongly, there will be a retain cycle and they won't get deallocated in the application lifetime.

In the above code, ViewController doesn't seem to hold reference of Cell. Hence I think it doesn't matter if I use protocol of type A and keep the strong reference of ViewController in cell.

But will my code be any safer if I declare the delegate property as a weakly referenced property? What are the implications of it?

Update:

Turns out that even if the ViewController is not holding direct reference of cell & even if TableView's reference is weak, ViewController is somehow holding strong reference to the cells. When I follow Method A, that is without declaring the delegate to be of weak reference. The deinit methods in Cell and ViewController never gets called. I checked in instruments too. The persistent retain count keeps increasing if I don't declare delegate as weak.

enter image description here

Now the big question is how is ViewController holding strong reference to the cells?


Solution

  • Deinitialization Process:

    When the view controller is popped out. Then deinit method is called.

    Then only all the other references that view controller is holding is cleared.

    Parents deinit triggers, child's deinit triggers then after all the deinit is traversed through then deallocation of parent is done finally at last.

    If any of the child is strongly referencing the parent. The deinit of parent never gets called and all the deinitialization process halts. In our case, since cell is retaining view controller strongly. The deinit method of ViewController never gets called. Hence The retain cycle. Here is great explanation for retain cycle.