如果代表是为对象之间的一对一关系而设计的,而NSNotifications是针对一对多关系而设计的,那么对于一对一关系是否有最佳实践?
我在iOS中看到了很多自定义多播代理,其中一个对象可以转换为多个订阅者(即Swift Language Multicast Delegate),但实现通常非常复杂并且看起来有点过分。一个这样的问题是安全地存储一组弱引用(代表)(How do I declare an array of weak references in Swift?)。
我已经看到很多建议(比如这个multiple listeners for delegate iOS),这表明这是NotificationCenter的目的。但是,为了一对一的关系而向以太网广播的想法本身似乎有些过分。
Apple的框架和Swift语言是否有最佳实践?我从来没有看到他们写过这个。 NotificationCenter是否适用于一对一关系,否则将需要多播代理?
我不会使用NotificationCenter
,因为消息的类型和发送者和接收者(观察者)之间的数据会丢失。使用Notification Center
将使您的代码依赖于Notification
对象,您需要使用通知的userInfo
字典来添加数据,这使得更难理解究竟是什么保留了通知(将需要查看数据在何时准确填充通知发送)。
委托是一个更好的解决方案,在弱代表列表中有超过1个代表是可以的。我已经在很多地方使用过这样的组合,我需要向一个特定的事件注册超过1个监听器并且工作得很好。
您可以创建一次委托集合,并在代码中轻松地重用它。这是我的解决方案:
class WeakContainer {
private weak var value: AnyObject?
public init(value: AnyObject) {
self.value = value
}
func get() -> AnyObject? {
return self.value
}
}
class DelegatesCollection<T>: Sequence {
private lazy var weakDelegates = [WeakContainer]()
var delegates: [T] {
return self.weakDelegates.map() { $0.get() as! T }
}
var hasDelegates: Bool {
return !self.weakDelegates.isEmpty
}
init() { }
func add(delegate: T) {
var exists = false
for currentDelegate in self.weakDelegates {
if(currentDelegate.get() === (delegate as AnyObject)) {
exists = true
break
}
}
if(!exists) {
self.weakDelegates.append(WeakContainer(value: delegate as AnyObject))
}
}
func remove(delegate: T) {
var i = 0
for currentDelegate in self.weakDelegates {
if(currentDelegate.get() == nil || currentDelegate.get() === (delegate as AnyObject)) {
self.weakDelegates.remove(at: i)
break
}
i += 1
}
}
func makeIterator() -> IndexingIterator<[T]> {
return self.delegates.makeIterator()
}
}
我可以推测Apple框架只使用单个委托,因为调用委托时要执行的操作是业务逻辑。从Apple的角度来看,委派一些事件已经发生并让应用程序决定下一步该做什么就足够了,所以没有必要在框架层面支持多个代理。