Liam SY Kim
by Liam SY Kim
3 min read

Categories

This time, let us study about delegate pattern in swift.

In iOS, delegate pattern is used many times including tableview, colelctionview.. etc.

When I first used it from tableview, because I have no understanding about protocols as well, it is like a magic.

Just adding TableViewDelegate makes it works.

So, my first question at that time is not Why?, but How?.

That’s why I introduce you the example code of delegate pattern here.

First, we study the concepts, and then study the examples.

Concepts

I will represent two classes as two people. They are Amanda and Yulia.

Amanda is packing boxes for delivery. Because yulia manages addresses to deliver, amanda should ask address to Yulia.

After get the address from Yulia, Amanda inform completion and results to Yulia.

Amanda knows all process about packing box, but Yulia do not need to know whole proecess.

Because Amanda knows whole process, she ask some works (delegate protocol) to Yulia.

As a result, Yulia just gives addresses.

We do not want to know whole process when we develope tableview or collectionview..

We just be informed what to do for those views from TableView and CollectionView.

In Swift, ViewController is Yulia, and Both TableView and CollectionView are Amanda.

That is why we use delegate pattern often in swift.

Examples

UITableView

I want you to explain it by following the way which I studied.

In the tableview,

class MyTableViewController : UIViewController, UITableViewDelegate {
	let myTableView: UITableView = UITableView() 
    override func viewDidLoad() {
      super.viewDidLoad()
	   self.myTableView.delegate = self
    }
    ...
}

Just typing self.myTableView.delegate = self and adding UITableViewDelegate makes us to use tableview.

Okay.. Delegate means do the work alternatively as you know,

What a magic by adding assigning self on the tableview variable delegate!

For further understanding, I dive into the internal of UITableView.

open class UITableView : UIScrollView, NSCoding, UIDataSourceTranslating {

    
    public init(frame: CGRect, style: UITableView.Style) // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain

    public init?(coder: NSCoder)
    
    weak open var dataSource: UITableViewDataSource?

    weak open var delegate: UITableViewDelegate?
    ...
}

Humn:open_mouth: .. delegate is declared on UITableView class which type is UITableViewDelegate.

Okay.. then What is UITableViewDelegate?

public protocol UITableViewDelegate : UIScrollViewDelegate {

    @available(iOS 2.0, *)
    optional func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)

    @available(iOS 6.0, *)
    optional func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)

    @available(iOS 6.0, *)
    optional func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int)
    ...
}

Some methodes which are changable depend on situation is defined at delegate protocol.

So, self.myTableView.delegate = self fill the abstracted method from the class, and then it is excuted from the UITableView which delegate property is declared on UITableView!!

I understand the flow.. but not fully understand.

For making my own delegate pattern, I wrote an example.

AnimalNameShowDelegate

I want to store animal name on Animal class , and show animal name. This should be proccessed on AnimalNameShowClass.

Overall functions are supported by Animal class, but the printing strings should be set by AnimalNameShowClass.

AnimalNameShowClass do delegated works that setting animal name and printing animal name.

From AnimalNameShow, works of animal will be proceeded by let animal = Animal()

Just func resultOfAnimalName(value : String) is filled by AnimalNameShowClass

class AnimalNameShowClass: AnimalNameShowDelegate {
    let animal = Animal()
    
    init() {
        animal.delegate = self
        animal.animalName = "lion"
        print("init")
    }
    deinit{
        print("deinit")
    }
    
    func resultOfAnimalName(value : String) {
        print("Animal name : \(value)")
    }
}

In protocol, we declare method which code is supported by AnimalNameShowClass.

By adding AnimalNameShowDelegate protocol on AnimalNameShowClass, We can forcing the work to define from AnimalNameShowClass

 protocol AnimalNameShowDelegate: class {
    func resultOfAnimalName(value : String)
}

Animal class has the code about animals except for resultOfAnimalName.

class Animal {
    init() {
        print("init")
    }
    deinit{
        print("deinit")
    }
    var delegate: AnimalNameShowDelegate?
    var animalName : String {
        set {
            self.delegate?.resultOfAnimalName(value: newValue)
        }
        get {
            return "No Animal"
        }
    }
}

Retain Cycle Issues

I already mentioned HERE about retain cycle concepts and examples.

Delegate pattern also reference each classes.

Protocol makes reference between classes.

Animal Class is declared on AnimalNameShowClass, and delegate protocol in Animal class references AnimalNameShowClass.

Conclusion

I wrote about Delegate pattern, and Completion Handler already, then I will write Observer pattern as soon as possible.

Additionally, I hope to write the comparision between those three patterns.

Thank you for read my blog. Hope it helps you:)