对于一对一关系:NotificationCenter或多播代理?

问题描述 投票:1回答:1

如果代表是为对象之间的一对一关系而设计的,而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个回答
2
投票

我不会使用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的角度来看,委派一些事件已经发生并让应用程序决定下一步该做什么就足够了,所以没有必要在框架层面支持多个代理。

© www.soinside.com 2019 - 2024. All rights reserved.