Концепция протокола очень проста: это всего лишь обещание, что определенные методы и / или свойства будут существовать в любом объекте, принятом по этому протоколу.И поэтому мы используем их для ввода и безопасности типов.
Представьте себе создание пользовательского элемента управления, например, листа действий:
class CustomActionSheet: UIControl {
func userTappedOnSomething() {
// user tapped on something
}
}
... и вы реализовали его в одном из ваших контроллеров представления.
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
}
}
Это бесполезно, если лист действий не позволяет общаться с контроллером представления, когда пользователь нажимает на кнопку.Поэтому мы используем делегата:
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
}
}
Теперь, когда пользователь нажимает кнопку на листе действий, контроллер представления внизу может обновить свой пользовательский интерфейс.Но это на самом деле не скомпилируется.Вы получите ошибку, что UIViewController
не имеет члена userTookAction
.Это связано с тем, что у класса UIViewController
нет метода с именем userTookAction
, только у этого экземпляра контроллера представления.Поэтому мы используем протокол:
protocol ActionSheetProtocol: AnyObject {
func userTookAction()
}
Этот протокол говорит, что любой объект, который ему соответствует, должен включать этот метод.Таким образом, мы изменяем делегат листа действий на этот тип протокола и подстраиваем контроллер представления к этому протоколу, так как он имеет такой метод:
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
}
}
Это классический пример использования протокола в Swift, и как только выПонимая это, вы узнаете, как стать хитрым с протоколами и использовать их очень умным способом.Но независимо от того, как вы их используете, концепция остается: обещает, что вещи будут существовать.
Примечание: В этом примере я назвал протокол ActionSheetProtocol
, потому что для кого-то, изучающего протоколы,это имеет смысл.Однако в мире Swift в сегодняшней практике большинство программистов (включая парней из Apple) назвали бы это ActionSheetDelegate
.Это может сбивать с толку тех, кто изучает протоколы, поэтому в этом примере я попытался сделать это как можно более понятным.Лично мне не нравятся имена делегатов протоколов, но есть много вещей, которые мне не нравятся.
Примечание 2: Я также сделал протокол типа AnyObject
, который является синтаксисом Swiftдля того, чтобы сделать протокол протоколом класса.Не все протоколы должны быть типа AnyObject
.