LNZWeakCollection
代理模式是一种常用的在对象之间传递消息和值的模式。
我们都知道这种模式的潜在问题
- 代理对象必须拥有一个弱引用以避免保留循环。
- 代理对象必须确保代理符合代理协议,否则可能会导致由于不识别选择器而崩溃。
如果期望的行为是让更多对象监听回调,并且您打算使用代理模式来处理多个代理,您可能会这样做
class MyProxy: NSObject, UITableViewDelegate {
weak var delegate1: UITableViewDelegate?
weak var delegate2: UITableViewDelegate?
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate1?.tableView?(tableView, didSelectRowAt: indexPath)
delegate2?.tableView?(tableView, didSelectRowAt: indexPath)
}
}
这种方法当然可以工作。但这非常不灵活。您只能有 2 个代理,并且显然如果您想添加更多,您必须添加 delegate3 var,记得更新所有方法等等。
这个问题的解决方案是什么?我们希望更加灵活,以避免大量的猴子工作。我们不能使用数组,因为它们会导致对象保留最终导致保留循环,而且我们也不能用 NSHashTable 和 NSMapTable,因为它们的零化行为并不总是符合预期。特别是NSMapTable 保留对象,直到数据结构需要调整大小。这意味着不清楚,但结论是,如果您想要释放弱引用,它们是不可靠的。
LNZWeakCollection 包含一个弱引用集合(WeakCollection)和一个具有弱键或弱值(WeakDictionary)的字典。
使用 WeakCollection,您将能够这样做
public class TableViewDelegateProxy: NSObject, UITableViewDelegate {
var delegates = WeakCollection<UITableViewDelegate>()
public func addDelegate(object: UITableViewDelegate) {
delegates.add(object: object)
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegates.execute { (delegate) in
delegate.tableView?(tableView, didSelectRowAt: indexPath)
}
}
}
Weak collection 遵循 Sequence 协议,因此您可以通过对象迭代
var delegates = WeakCollection<UITableViewDelegate>()
for (i, delegate) in delegates.enumerated() {
delegate.tableView?(tableView, didSelectRowAt: indexPath)
}
for delegate in delegates {
delegate.tableView?(tableView, didSelectRowAt: indexPath)
}
要安装它,您可以将 swift 文件拖放到项目中,或者通过 Cocoapod 进行安装
pod 'LNZWeakCollection'