Delegates and Closure in Swift: Made Easy!

Navid Mostafiz
3 min readFeb 18, 2020

Previously, I was writing about Closures in JavaScript. To my surprise, I found that Delegating a function throughout a Swift application module also provides closure. “And What is closure again?” Closure is the original scope of a function that it retains even when it has been passed to some other part of the application through a delegate. Due to closure, the function will still have access to the variables it originally had, no matter where it is being executed from, it will still be able to use those variables (actually, anything in general).

Let me quote what I wrote on closure earlier:

“A closure is a scope or environment that a function captures. The scope of a function is always outward. It begins with its local scope and then to its outer scopes up to the global scope. It can access anything in its scope. However, it cannot access things from an inner scope created by an inner function in its local scope or cannot access something from the scope of other functions in the global scope. And that being said: The function will always retain its original scope. Even if we assign this function to a delegate/variable (first-class object) and is delegated or passed to some other class/function and it will be invoked somewhere, it will still retain its original scope as mentioned before and will still have access to anything that it had. So, the function captures its scope for all time to come. This is called closure provided by the functions.”

The below basic example, shows how the function provided by a protocol is being used by multiple classes and the same instance of that protocol is being passed between classes using delegates. The code is explained with comments. Let's go through it:

import UIKit

//THE PROTOCOL
protocol DataPass {
func dataPassing(name: String, address: String, city: String)
}

//SECOND ViewController CLASS
class SecondViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
}

@IBOutlet var textName: UITextField!
@IBOutlet var textAddress: UITextField!
@IBOutlet var textCity: UITextField!

//DELEGATE IS JUST A PROPERTY OF THIS CLASS, IT JUST HOLDS INSTANCE OF PROTOCOL
var delegate:DataPass!

//USING DELEGATE, FUNCTION OF THE PROTOCOL IS BEING CALLED
//dataPassing() function still retains its original scope
@IBAction func buttonSaveClick(_ sender: Any) {
delegate.dataPassing(name: textName.text!, address: textAddress.text!, city: textCity.text!)
}

}

Now, we have the View Controller class which provides ViewController for our app:

import UIKit

//View Controller CLASS, IMPLEMENTS PROTOCOL
class ViewController: UIViewController, DataPass {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}

@IBOutlet var lblName: UILabel!
@IBOutlet var addressLbl: UILabel!
@IBOutlet var cityLbl: UILabel!


@IBAction func buttonGoClick(_ sender: Any) {
let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
//SECOND CLASS = SecondViewController HAS A PROPERTY CALLED delegate
//WE WILL PASS self TO THE SECOND CLASS USING THIS delegate
secondVC.delegate = self
self.navigationController?.pushViewController(secondVC,animated: true)
}

//WHEN SECOND CLASS WILL CALL dataPAssing() function using delegate,
//IT WILL ACTUALLY CALL THIS FUNCTION BELOW, IMPLEMENTED BY THIS CLASS
func dataPassing(name: String, address: String, city: String) {
lblName.text = name
addressLbl.text = address
cityLbl.text = city
}

}

I Hope, the code example above will provide a simple glimpse of how the delegate was used and how the delegated function provided closure.

--

--