Delegate Pattern - Swift Programming

Feb 12, 2018 delegates swift programming macosx
WhatsApp
In many of the guides and tutorials I came across, many of them suggested a one to one usage. Here I’ll use multiple delegates to update the StatusBarItem title and a NSTextfield.

First off what are Delegates. It’s a programming paradigm allowing one object to pass data to another object at any point within the program. It is able to do this because both these objects are related by passing a reference of object A which object B holds. I think it’s important to reiterate this, as this is what connects these two objects together. I found this really helpful when using the MVC pattern as I tripped over, when my variable within my Model object had updated but it wasn’t able pass data to my controller. As an example - updating a UI label.

Imagine we’re making an app that updates the view label. We have our model class Price and our view controller PriceViewController.



class Price {

var currPrice: Double

init (currPrice: Double) {
self.currPrice = currPrice
}
}


Now we’ll add the delegate variable to the class we’ll also need the protocol it’ll conform to and add our observers.


class Price {
let priceViewControllerDelegate: PriceProtocol? // Add the delegate!
var currPrice: Double {
willSet {

}
didSet {
self.priceViewControllerDelegate?.updatePrice(self.price)
}
}

init (currPrice: Double) {
self.currPrice = currPrice
}
}



Let’s define the protocol. You may add this into an individual file or outside the scope of the Price class. The class keyword in the definition means, it can only be applied to a class.


protocol PriceProtocol: class {
func updatePrice(_ price: String?)
}


Let’s connect the two objects together. For this example we’ll pretend that the View Controller is the first place the application will visit when executed. I’ve set up the view controller with a label and the protocol implementation


class PriceViewController: NSViewController, TickerPriceProtocol {

@IBOutlet weak var priceLabel: NSTextField!

override func viewDidLoad() {
super.viewDidLoad()

}

/*
Protocol implementation
*/
func updatePrice(_ price: String?) {
if let myPrice = price {
self.priceLabel.stringValue = myPrice
}
}
}


If we look at the protocol implementation of updatePrice, we can see that we receive a price value from some where in the application. As I said before, I believe that the most important part of the delegate is understanding how the two connect to each other.

As I mentioned earlier, the ViewController will be our initial execution point. Currently there isn’t a link made between the two classes, let’s create this.


class PriceViewController: NSViewController, TickerPriceProtocol {

@IBOutlet weak var priceLabel: NSTextField!
let priceObject = Price
override func viewDidLoad() {
super.viewDidLoad()
priceObject.priceViewControllerDelegate = self // the link
}

/*
Protocol implementation
*/
func updatePrice(_ price: String?) {
if let myPrice = price {
self.priceLabel.stringValue = myPrice
}
}
}



If we look at the line

priceObject.priceViewControllerDelegate = self

we can see that we are passing a reference of the view controller object to the priceViewControllerDelegate. Now whenever we update the price like so



priceObject.price = 4.4 //new price



didSet will execute and run the updatePrice function referenced by our priceViewControllerDelegate which is a reference of our viewcontroller.
While reading various articles about delegates online, all mentioned that delegates are generally one to one. A true statement, but an idea popped up to extend this further and apply a collection of delegates with a function to search and find the delegate we are looking for or perhaps is that what Key Value Observers are for? I’ll have to look into that over the week.

If you found the following info helpful, I'm happy to accept any donations of the following cryptocurrencies.

  • Bitcoin - 17DTiPExzP9StqveW428acEyB4mVMfKbiK
  • Ethereum - 0x87B8307FD20dc90cc05c94905Ec593134D32B6FF
  • Litecoin - LZMiz5U5sVq9doMLYE3gfLJrxCQDKuyCmU
  • Neo - AXv71WB38ajc1KUUEnxQKhynLLPc4BapVb