协议的概念非常简单:它只不过是一个承诺,即特定方法和/或属性将存在于该协议所采用的任何对象中。因此,我们将它们用于打字和打字安全。
想象一下创建一个自定义控件,如操作表:
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
}
}
现在,当用户点击操作表中的按钮时,下面的视图控制器可以更新其 UI。但这实际上不会编译。你会得到一个UIViewController
没有 member的错误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 的语法,用于使协议成为类协议。并非所有协议都需要是 type AnyObject
。