【发布时间】:2014-07-05 12:11:35
【问题描述】:
在 Objective-C 中,我经常绕过块。我经常使用它们来实现有助于避免将内容存储到实例变量中的模式,从而避免线程/时序问题。
例如,我通过-[CAAnimation setValue:forKey:] 将它们分配给CAAnimation,这样我就可以在动画完成时执行该块。 (Objective-C 可以将块视为对象;您也可以这样做 [someBlock copy] 和 [someBlock release]。)
然而,在 Swift 中尝试将这些模式与 Objective-C 一起使用似乎非常困难。 (编辑:我们可以看到该语言仍在不断变化:已经修改了代码,使其适用于 Xcode6-beta2,之前的版本适用于 Xcode6-beta1。)
例如,我无法将 AnyObject 转换回块/闭包。以下会从编译器产生错误:
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'
}
我找到了一种解决方法,但它非常难看,恕我直言:在我的桥接头中,我有:
static inline id blockToObject(void(^block)())
{
return block;
}
static inline void callBlockAsObject(id block)
{
((void(^)())block)();
}
现在我可以在 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)
}
它可以工作,但我需要为我想使用的每种块类型提供一个新函数,而且我正在修改编译器,这也不好。
那么有没有办法以纯 Swift 的方式解决这个问题?
【问题讨论】:
-
animation.setValue(completion, forKey: "completionClosure")行在我的 Xcode 6 beta 2 项目中无法编译。 -
@MartinR:谢谢,还在使用 beta 1。已经更新了问题……它变得更糟了。
标签: objective-c closures swift block