UIKit Delegate Protocol Pattern

Aug 19, 2022 2 min read
UIKit Delegate Protocol Pattern

When you want to communicate between different screens it is very common to use one of the two patterns, either:

  • Delegate protocols
    This is a one to one communication method, one view communicates to another view.
  • Notifications and observers
    This is a one-many patter. So you can have 1 observer and 10 different notifications pointing to that one observer.

In this article I'll be focusing on the Delegate pattern.

Delegate is a pattern widely used in iOS development to exchange messages between objects. It allows an object to communicate back with its owner.

How does it work?

Imagine you have screen 1VC and 2VC. Delegation works for passing data back from 1VC to 2VC

I'll use the analogy from Sean which I think is awesome. Imagine you have 2 screens. Once you tap on Choose a Side it goes to the "boss" screen to pick an image. So, for example, the intern would be your UIViewController and Boss your UITableViewCell. Here are their roles:

  • Intern
    Doesn't know how to do the actions, he's just waiting for the boss' orders.
  • Boss
    The boss knows about what needs to be done and how to do it.

Delegate functions

You can add as many functions as you'd like, for now I'll add only one. So to the analogy of the intern/boos, we are going to add the functions to our boss:

Naming: Apple's naming pattern is to name the protocol with the name of the class and ending in Delegate.
protocol MyViewTableCellViewDelegate: AnyObject {
    func didTapButton()
}

Next create the delegate that will be used to communicate ("the intern")

weak var delegate: MyViewTableCellViewDelegate?

Next create the function of what you want the delegate to do once it's called ("what you want the intern to do"). So we are sending information back to the intern based on some things the boss did.

@objc func goToBossPage(sender: UIButton) {
    delegate.didTapButton()
}

Conforming to the protocol on the main view

Now that you created the protocol, it's time to use it on yourUIViewController. Think of it like "the intern getting the job"

Let's supposed the UIViewController is called MyViewViewController. Create an extension like:

extension MyViewViewController: MyViewTableCellViewDelegate {
    func didTapButton(buttonName: String) {
        guard let navigationController = navigationController else { return }
        present(BossView(), animate: true, completion: nil)
    }
}

If you are using a UITableView on at the time of the cell setup, make sure you assign the delegate, pay attention to setupMyBossCell where the delegate is assigned to self:

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var tableViewCell: UITableViewCell
    guard let sectionName = sectionNameAt(section: indexPath.section) else { return UITableViewCell() }
    if let mySections = MySectionEnum(rawValue: sectionName) {
        switch mySections {
        case .myBossSection:
            tableViewCell = setupMyBossCell(indexPath)
        }
    } else {
        guard let delegate = delegate else { return UITableViewCell() }
        tableViewCell = delegate.cellAt(indexPath: indexPath, tableView: tableView)
    }
    return tableViewCell
}

private func setupMyBossCell(_ indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: MyBossCell.reuseIdentifier, for: indexPath) as? MyBossCell else { return UITableViewCell() }
    cell.delegate = self
    return cell
}

If you are using another UIViewController or any other kind of View to display the boss page and not , just create a function and call it on the init(), again assigning the delegate to self, something like:

// This is an example with storyboard, programatically is very similar
func chooseButtonTapped(_ sender: UIButton) {
    let selectionVC = storyboard?.instantiateViewController(withIdentifier: "SelectionScreen") as! SelectionScreen
    selectionVC.delegate = self
    present(selectionVC, animate: true, completion: nil)
}
Great! Next, complete checkout for full access to ArturoFM.
Welcome back! You've successfully signed in.
You've successfully subscribed to ArturoFM.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.