委托模式
一个代表是可可和 CocoaTouch 框架使用了常见的设计模式,在实现一些功能到另一个类代表的责任。这遵循关注点分离的原则,其中框架类实现通用功能,而单独的委托实例实现特定用例。
查看委托模式的另一种方法是在对象通信方面。Objects
经常需要相互交谈,并且这样做一个对象需要符合 protocol
才能成为另一个 Object 的委托。完成此设置后,另一个对象会在有趣的事情发生时与其代理进行对话。
例如,用户界面中用于显示数据列表的视图应仅负责数据显示方式的逻辑,而不是用于决定应显示哪些数据。
让我们深入研究一个更具体的例子。如果你有两个类,父母和孩子:
class Parent { }
class Child { }
并且你想要通知父母孩子的更改。
在 Swift 中,代表是使用 protocol
声明实现的,因此我们将声明 protocol
将实现的 protocol
。这里代表是 parent
对象。
protocol ChildDelegate: class {
func `childDidSomething()`
}
子进程需要声明一个属性来存储对委托的引用:
class Child {
weak var delegate: ChildDelegate?
}
注意变量 delegate
是可选的,协议 ChildDelegate
被标记为仅由类类型实现(没有这个 delegate
变量不能被声明为 weak
参考,避免任何保留周期。这意味着如果 delegate
变量不再在其他地方引用,它将被释放)。这样父类只在需要和可用时才注册委托。
另外,为了将我们的代理标记为 weak
,我们必须通过在协议声明中添加 class
关键字来约束我们的 ChildDelegate 协议以引用类型。
在这个例子中,当孩子做某事并需要通知其父母时,孩子会调用:
delegate?`.childDidSomething()`
如果已定义代理,则将通知代理该孩子已做某事。
父类需要扩展 ChildDelegate
协议才能响应其操作。这可以直接在父类上完成:
class Parent: ChildDelegate {
...
func `childDidSomething()` {
print("Yay!")
}
}
或者使用扩展名:
extension Parent: ChildDelegate {
func `childDidSomething()` {
print("Yay!")
}
}
父母还需要告诉孩子这是孩子的代表:
// In the parent
let child = `Child()`
child.delegate = self
默认情况下,Swift protocol
不允许实现可选功能。只有在你的协议标有 @objc
属性和 optional
修饰符时,才能指定这些。
例如,UITableView
实现了 iOS 中表视图的通用行为,但是用户必须实现两个名为 UITableViewDelegate
和 UITableViewDataSource
的委托类,它们实现特定单元格的外观和行为方式。
@objc public protocol UITableViewDelegate : NSObjectProtocol, UIScrollViewDelegate {
// Display customization
optional public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
optional public func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
optional public func tableView(tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int)
optional public func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
...
}
你可以通过更改类定义来实现此协议,例如:
class MyViewController : UIViewController, UITableViewDelegate
必须实现在协议定义中未标记 optional
的任何方法(在本例中为 UITableViewDelegate
)。