The concept of the protocol is very simple: it's nothing more than a promise that specific methods and/or properties will exist in whatever object has taken on that protocol. And so we use them for typing and type safety.
Imagine creating a custom control, like an action sheet:
class CustomActionSheet: UIControl {
func userTappedOnSomething() {
// user tapped on something
}
}
...and you implemented it in one of your view controllers.
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
}
}
This isn't much use without allowing the action sheet to communicate with the view controller when the user taps on a button. So we use a delegate:
class CustomActionSheet: UIControl {
weak var delegate: UIViewController?
func userTappedOnSomething() {
delegate?.userTookAction()
}
}
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
actionSheet.delegate = self
}
func userTookAction() {
// update the UI
}
}
Now when the user taps on a button in the action sheet, the view controller underneath can update its UI. But this actually won't compile. You will get an error that UIViewController
has no member userTookAction
. That is because the UIViewController
class doesn't have a method called userTookAction
, only this instance of the view controller does. So we use a protocol:
protocol ActionSheetProtocol: AnyObject {
func userTookAction()
}
This protocol says that whatever object that conforms to it must include this method. So we change the action sheet's delegate to be of that protocol type and we conform the view controller to that protocol since it has such method:
class CustomActionSheet: UIControl {
weak var delegate: ActionSheetProtocol?
func userTappedOnSomething() {
delegate?.userTookAction()
}
}
class SomeViewController: UIViewController, ActionSheetProtocol {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
actionSheet.delegate = self
}
func userTookAction() {
// update the UI
}
}
This is a classic example of protocol use in Swift and once you understand it, you will learn how to get crafty with protocols and use them in very clever ways. But no matter how you use them, the concept remains: promises that things will exist.
Note: In this example, I named the protocol ActionSheetProtocol
, because to someone learning protocols, it makes the most sense. However, in the Swift world, in today's practice, most programmers (including the guys at Apple) would name it ActionSheetDelegate
. This can be confusing for someone learning protocols so in this example I tried to make it as clear as possible. I personally don't like naming protocols delegates but there’s a lot of things I don’t like.
Note 2: I also made the protocol of type AnyObject
which is Swift's syntax for making the protocol a class protocol. Not all protocols need to be of type AnyObject
.