协议的概念非常简单:它只不过是一个承诺,即特定方法和/或属性将存在于该协议所采用的任何对象中。因此,我们将它们用于打字和打字安全。
想象一下创建一个自定义控件,例如操作表:
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 没有成员 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 类型。