浇铸闭合/块 [英] Cast closures/blocks

查看:145
本文介绍了浇铸闭合/块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆