【问题标题】:For one-to-few relationships: NotificationCenter or multicasting delegate?对于一对多关系:NotificationCenter 还是多播委托?
【发布时间】:2019-04-18 21:20:38
【问题描述】:

如果委托是为对象之间的一对一关系设计的,而 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 是否适合用于需要多播委托的一对多关系?

【问题讨论】:

    标签: ios swift delegates nsnotificationcenter


    【解决方案1】:

    我不会使用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 的角度来看,委托某些事件已经发生并让应用程序决定下一步做什么就足够了,因此在框架级别支持多个委托是没有意义的。

    【讨论】:

      猜你喜欢
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 2017-07-04
      • 1970-01-01
      • 2015-12-23
      • 2019-07-17
      相关资源
      最近更新 更多