Protocol
s allow you to define functions and properties that any class or struct which conforms to it must implement. This gives you the ability to rely only upon the things you need, while not putting too many restrictions on the conforming type. Let’s look at an example.
Consider the following:
protocol Fireable { func fire() }
This protocol requires that implementers have a function called fire. You could then make various classes conform to it, like so:
class NetworkCall: Fireable { // ... other properties and functions ... func fire() { // fire the network call here } }
Then, you could rely on Fireable
instead of NetworkCall
in any view controller you were building:
class ListOfThingsViewController: UITableViewController { // ... other stuff ... var call: Fireable? override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) call?.fire() } // ... more stuff ... }
This allows you to easily switch out different implementations of the protocol without changing all the stuff that relies upon it. You can also use extensions to add protocol conformity to an existing class or struct:
extension URLRequest: Fireable { func fire() { let session = URLSession(configuration: .default, delegate: nil, delegateQueue: OperationQueue.main) let dataTask = session.dataTask(with: self) { _, _, _ in } dataTask.resume() } }
In ListOfThingsViewController
defined above combined with this extension, you could assign either a NetworkCall
or a URLRequest
to the call
property. This flexibility allows you to keep your UI code completely agnostic to many implementation details in your project.