Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
惯用的Swift多路复用通知?_Swift_Design Patterns_Notifications_Idioms_Generics - Fatal编程技术网

惯用的Swift多路复用通知?

惯用的Swift多路复用通知?,swift,design-patterns,notifications,idioms,generics,Swift,Design Patterns,Notifications,Idioms,Generics,我正在定义一个类结构,当有趣的事情发生在它身上时(获取新数据,等等),它需要通知它的使用者。类似于委托关系,但可能有许多使用者。而且这种关系比把一个NSNotification扔到风中更直接 在大多数Objective-C程序中,我倾向于定义一个协议,让那些消费者实现它并将自己注册为id;我会把它们塞进一个NSMutableSet,我会在适当的时候对其进行迭代。我花在编写C#上的时间会使我倾向于尝试在某种程度上修改这种方法,以便在Swift中使用泛型(a laprivate var myCons

我正在定义一个类结构,当有趣的事情发生在它身上时(获取新数据,等等),它需要通知它的使用者。类似于委托关系,但可能有许多使用者。而且这种关系比把一个
NSNotification
扔到风中更直接

在大多数Objective-C程序中,我倾向于定义一个协议,让那些消费者实现它并将自己注册为
id
;我会把它们塞进一个
NSMutableSet
,我会在适当的时候对其进行迭代。我花在编写C#上的时间会使我倾向于尝试在某种程度上修改这种方法,以便在Swift中使用泛型(a la
private var myConsumers=Set()
)。据我所知,那是一个又黑又痛的兔子洞。但与其深入研究,不如让我后退一步,尝试解决真正的问题

所以:我有一个类,在这个类中,实例需要将发生的有趣事情通知0-N消费者。允许这些消费者自己注册和注销会很好,因为他们的寿命可能比我的班级短


实现此模式的惯用Swift方法是什么?

这是我迄今为止能够想到的最简单的方法,可以进行模拟

struct多重关闭{
私有类型别名密钥=MultiClosureKey
私有let闭包:[键:T->U]
init(){closures=Dictionary U>()}
init(closure:T->U){closures=[Key():closure]}
私有init(closures:[Key:T->U]){self.closures=closures}
函数运行(t:t){
用于closures.values{closure(t)}中的闭包
}
}
私有类MultiClosureKey:可哈希{
//这是无知吗?我还不知道。
//这似乎有效,所以我还没有找到更好的解决方案。
var hashValue:Int{return ObjectIdentifier(self).hashValue}
}
private func==(lhs:MultiClosureKey,rhs:MultiClosureKey)->Bool{
返回lhs===rhs
}
func+(左:多闭,右:多闭)->多闭{
返回多闭包(左.闭包+右.闭包)
}
func+=(输入左:多闭,右:多闭){
左=左+右
}
func-(左:多闭,右:多闭)->multicclosure{
返回多闭包(左.闭包-右.闭包)
}
func-=(输入左:多闭,右:多闭){
左=左-右
}
字典扩展:

func + <T, U>(var left: Dictionary<T, U>, right: Dictionary<T, U>) -> Dictionary<T, U> {
    for (key, value) in right {
        left[key] = value
    }
    return left
}

func += <T, U>(inout left: Dictionary<T, U>, right: Dictionary<T, U>) {
    left = left + right
}

func - <T, U>(var left: Dictionary<T, U>, right: Dictionary<T, U>) -> Dictionary<T, U> {
    for key in right.keys {
        left[key] = nil
    }
    return left
}

func -= <T, U>(inout left: Dictionary<T, U>, right: Dictionary<T, U>) {
    left = left - right
}
func+(变量左:字典,右:字典)->Dictionary{
对于右侧的(键、值){
左[键]=值
}
左转
}
func+=(输入左:字典,右:字典){
左=左+右
}
func-(变量左:字典,右:字典)->Dictionary{
用于右键输入{
左[键]=零
}
左转
}
func-=(输入左:字典,右:字典){
左=左-右
}

Cocoa中多授权的惯用解决方案是通知,特别是使用
addObserverForName(对象:queue:usingBlock:)
。结束吧。保存返回值,并使用该返回值在将来注销您自己

有ObjC多播委托(可能是我实现的委托之外最喜欢的委托),但大多数情况下,它的麻烦比它的价值还多。通知是Cocoa管理非委派观察员的方式

“非委托”在这里的意思是“被通知的事情,但从来没有问过任何问题。”多委托的问题是,它实际上是一个毫无意义的术语。“代表”是指你要求提供信息的东西;你“委派”决策责任的事情。观察员并不是真正的“代表”(尽管代表有时是观察员)。你什么都不要问他们。他们无法控制决策。因此,多重委托是无稽之谈。多件事怎么可能都有责任回答一个问题?为了使这更具体,代理具有非
void
方法。考虑一下对于“代码> UITable VIEW委托程序< /COD>有多个委托意味着什么。您将如何确定行高是多少


如果您正在构建自己的,我可能会建议您使用
DictionaryVoid>
,其中“key”是您返回给调用方以便稍后删除的句柄。这样你就不必担心闭包平等的疯狂性(我同意Chris Lattner的观点,这是一个非常开放的、可能无法解决的问题).

我编写了一个本机Swift通知广播系统,它使开发人员能够使用switch-case语法匹配特定的通知类型,并与NSNotificationCenter的工作方式相同

我现在处理的通知如下:

func handleNotification(notification: PrimitiveNotificationType) {  
    switch notification {
    case let aNotification as CustomNotification:
        let initialFrame = aNotification.initialFrame
        let finalFrame = aNotification.finalFrame
        print("Initial frame: \(initialFrame)")
        print("Final frame: \(finalFrame)")
    default: return
    }
}
以下是帖子:

代码如下:


另外,这些东西只能在Swift 2上使用。

为什么你认为
Set()
是一个黑暗而痛苦的兔子洞?除了一个显而易见的问题,即Set在1.1版(在1.2版中)还没有实现,但通过使用数组很容易解决这个问题。我可能会发布另一个关于这个问题的问题,但实际上与这个问题无关。Objective-C和Swift都没有“习惯性地”解决过这个问题。去年我在论坛上与Swift创作者交谈时,他们甚至不知道为什么你需要一个多播代理;你将很难让非C用户理解一个像样的解决方案,正如你所描述的。我使用一个包装器类,它循环遍历一组闭包,并运行每一个闭包,直到出现一个合适的语言级解决方案。@Jessy闭包数组似乎足够简单,可以实现,但似乎不可能在消费者离开时选择性地取消注册,是吗?应该可以;我们应该能够从集合中移除闭包。因为这还没有实现(即,您无法测试闭包是否相等),所以我们需要将闭包包装在可以从集合中删除的内容中。从Chris Lattner那里了解。你关于这不是dele的观点
func handleNotification(notification: PrimitiveNotificationType) {  
    switch notification {
    case let aNotification as CustomNotification:
        let initialFrame = aNotification.initialFrame
        let finalFrame = aNotification.finalFrame
        print("Initial frame: \(initialFrame)")
        print("Final frame: \(finalFrame)")
    default: return
    }
}