有没有办法为闭包创建泛型类型签名,以便我以后可以一般地调用它?特别是我的问题是如何处理未知数量的论点。
我有一个对象,我想在更新时调用一系列闭包,我希望其他对象能够注册他们希望用第一个对象调用的闭包。
闭包是不可删除的,但我希望能够取消注册一个闭包,所以我最终创建了一个自定义类型来处理这个基于字典:
//T is the block signature such as Double->()
struct ClosureCollection<T> : SequenceType {
private var idx=0
var closureDict:[Int:(T,NSOperationQueue)]=[:]
mutating func addClosure(b:T) -> Int {
return addClosure(NSOperationQueue.mainQueue(),b)
}
mutating func addClosure(q:NSOperationQueue, _ b:T) -> Int {
closureDict[idx]=(b,q)
idx+=1
return idx-1
}
mutating func dropClosure(k:Int) {
closureDict.removeValueForKey(k)
}
func generate() -> AnyGenerator<(T,NSOperationQueue)> {
var dgen=closureDict.generate()
return AnyGenerator {
return dgen.next()?.1
}
}
}
这让我可以在这样的代码中使用集合:
声明:
private var distributionPoints=ClosureCollection<(CMDeviceMotion?,NSError?) -> ()> ()
使用它:
for (p,q) in distributionPoints {
q.addOperationWithBlock {p(dm,error)}
}
到目前为止,一切都很好,但它要求调用者遵循一个非常具体的模式来使用我想隐藏的集合。我想将这个想法扩展到我可以要求集合使用类似
之类的语法来运行for循环的地方distributionPoints.runAllWith(dm,error)
问题在于runAllWith签名 - 我当前的实现在完整的闭包签名上是通用的,因为我不知道如何使闭包的参数数量通用。我怀疑如果我知道块接受一个参数并返回一个参数,例如,通过使用两个类型的占位符,比如说T代表参数,U代表返回值,我就可以这样做。
我似乎无法做的是在未知数量的参数中使这个通用。我正在创建的类型并不关心块的结构是什么,它只是想接受具有特定签名的闭包,然后通过公开依赖于闭包签名的API来提供调用它们的机制。
我认为不存在对可变参数的支持,所以我不能走这条路。 Tuple-splat已被弃用。
有没有办法做到这一点,而不需要调用者将参数捆绑到元组中,然后需要在每个闭包周围打开包装来解开参数元组并做一个手工制作的元组splat?