浇铸闭合/块 [英] Cast closures/blocks
问题描述
在Objective-C中,我经常传递块。我经常使用它们来实现模式,这有助于避免存储东西到实例变量,从而避免线程/时序问题。
In Objective-C, I often pass around blocks. I use them very often to implement patterns that help avoid storing stuff into instance variables, thus avoiding threading/timing issues.
例如,我将它们分配给一个 CAAnimation
via - [CAAnimation setValue:forKey:]
所以我可以在动画完成时执行块。 (Objective-C可以把块当作对象;你也可以做 [someBlock copy]
和 [someBlock release]
。 )
For example, I assign them to a CAAnimation
via -[CAAnimation setValue:forKey:]
so I can execute the block when the animation is finished. (Objective-C can treat blocks as objects; you also can do [someBlock copy]
and [someBlock release]
.)
但是,试图在Swift中使用这些模式和Objective-C似乎是非常困难的。 (修改),我们可以看到该语言仍在不断变化:已修改代码,使其适用于Xcode6-beta2,以前的版本适用于Xcode6-beta1。)
However, trying to use these patterns in Swift together with Objective-C seems to be very difficult. ( and we can see that the language is still in flux: have adapted the code so it works on Xcode6-beta2, previous version worked on Xcode6-beta1.)
例如,我不能将 AnyObject
转换回块/闭包。下面的代码从编译器产生错误:
For example, I can't convert AnyObject
back to a block/closure. The following yields an error from the compiler:
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
(completion as (@objc_block ()->Void))()
// Cannot convert the expression's type 'Void' to type '@objc_block () -> Void'
}
我找到了一个解决方法,但是很丑陋我的桥接头,我有:
I have found a workaround, but it's pretty ugly, IMHO: in my bridging header, I have:
static inline id blockToObject(void(^block)())
{
return block;
}
static inline void callBlockAsObject(id block)
{
((void(^)())block)();
}
现在我可以在Swift中执行:
And now I can do this in Swift:
func someFunc(completion: (@objc_block ()->Void))
{
let animation = CAKeyframeAnimation(keyPath: "position")
animation.delegate = self
animation.setValue(blockToObject(completion), forKey: "completionClosure")
…
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
callBlockAsObject(completion)
}
它工作,但我需要一个新的功能,我想使用的每个块类型,我在编译器,这是不好的。
It works, but I'd need a new function for every block type that I'd like to use and I'm hacking around the compiler which can't be good either.
那么有没有办法以纯粹的Swift方式解决这个问题?
So is there a way to solve this in a pure Swift way?
推荐答案
$ c> Block 参数化的函数类型?
How about a generic Block
parameterized with the function type?
class Block<T> {
let f : T
init (_ f: T) { self.f = f }
}
分配其中一个;它将是 AnyObject
的子类型,因此可以分配到字典和数组中。这看起来不太繁重,尤其是使用尾随闭包语法。正在使用中:
Allocate one of these; it will be a subtype of AnyObject
and thus be assignable into dictionaries and arrays. This doesn't seem too onerous especially with the trailing closure syntax. In use:
5> var b1 = Block<() -> ()> { print ("Blocked b1") }
b1: Block<() -> ()> = {
f = ...
}
6> b1.f()
Blocked b1
,另一个例子是阻止
类型被推断:
and another example where the Block
type is inferred:
11> var ar = [Block { (x:Int) in print ("Block: \(x)") }]
ar: [Block<(Int) -> ()>] = 1 value {
[0] = {
f = ...
}
}
12> ar[0].f(111)
Block: 111
这篇关于浇铸闭合/块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!