Delegation

A portrait painting style image of a pirate holding an iPhone.

by The Captain

on
July 25, 2023
Understanding Swift Delegation with Code Example

Understanding Swift Delegation with Code Example

The Swift programming language provides various powerful features for designing and implementing modular code. One such feature is delegation, which allows objects to communicate and pass data between each other in a highly decoupled manner. Delegation follows the delegation design pattern and is commonly used in many iOS and Swift applications.

To understand delegation better, let's consider a scenario where we have two classes, a ViewController class and a DataSource class. The ViewController is responsible for displaying content on the screen, while the DataSource is responsible for providing the data to be displayed. Instead of tightly coupling the classes, we can implement delegation to achieve loose coupling and maintain separation of concerns.

First, let's define a protocol called DataSourceDelegate that the ViewController will conform to:

protocol DataSourceDelegate: class {
    func didUpdateData(data: [String])
}

In this protocol, we define a single method didUpdateData that takes an array of strings as a parameter. This method will be called whenever the DataSource has updated data.

Now, let's implement the DataSource class:

class DataSource {
    weak var delegate: DataSourceDelegate?
    
    func fetchData() {
        // Simulating data retrieval and update
        let newData = ["Item1", "Item2", "Item3"]
        
        // Notify the delegate
        delegate?.didUpdateData(data: newData)
    }
}

In the above code, we have a property delegate of type DataSourceDelegate that represents the delegate object. We mark it as weak to prevent retain cycles. When the fetchData method is called, it retrieves new data and notifies the delegate.

Finally, let's implement the ViewController class:

class ViewController: DataSourceDelegate {
    let dataSource = DataSource()
    
    func start() {
        dataSource.delegate = self
        dataSource.fetchData()
    }
    
    func didUpdateData(data: [String]) {
        // Do something with the updated data
    }
}

In the ViewController class, we create an instance of the DataSource class and set the ViewController as the delegate. When the fetchData method is called, the DataSource will notify the delegate, calling the didUpdateData method in the ViewController. Here, we can handle the updated data and perform any necessary actions.

By using delegation, we achieve loose coupling between the ViewController and the DataSource. The ViewController doesn't need to know how the data is retrieved; it only needs to conform to the DataSourceDelegate protocol and handle the updated data. This separation of concerns improves code maintainability and reusability.

Summary: Delegation in Swift is a powerful feature that enables objects to communicate and pass data between each other in a decoupled manner. It promotes loose coupling and separation of concerns, leading to more modular and maintainable code.