If you have a ViewController with a TableView and you want the TableViewCells to be able to notify the ViewController to do something, there are a few ways you can do this:

  1. Notifications
  2. Delegates
  3. Closures

Let’s talk about #3, using closures.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") as? CustomCell else {
            return UITableViewCell()
        }
        
        cell.closure = {
            doSomething()
        }
        
        return cell
    }

In the TableView’s cellForRow when we instantiate the cell we give it a closure that when fired will cause self to doSomething(). The CustomCell needs a variable to store the closure the ViewController hands it.

class CustomCell: UITableViewCell {

    var closure: (() -> ())?

You might’ve noticed Xcode complained.

Self Capture Semantics

This means that the function doSomething() will maintain a strong reference to self (the ViewController) and this strong reference can cause a retain cycle, causing neither the ViewController nor the cell to deallocate from memory.

We can force the self reference to be weak like this:

cell.closure = { [weak self] in
    self?.doSomething()
}

But we cannot do this:

func doSomething() {
    [weak self] in
}
    
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") as? CustomCell else {
        return UITableViewCell()
    }
    
    cell.closure = doSomething
    
    return cell
}

Closure Syntax Problem

You can’t use closure syntax for [weak self] inside a normal function. So if we’ve stored the function doSomething in a variable, or if we intend to pass that closure around deeper inside the TableViewCell, we will run into memory leaks. ARC won’t deallocate our ViewControllers or TableViewCells.

The alternative methods (#1. Notifications or #2. Delegates) solve the problem in different ways and don’t suffer the same memory retention problems. Closures are awesome though, as long as you are aware of the risks. Make sure all of your references to self inside them are weak.