这不是错误。这只是你的闭包类型是错误的。
正确的类型应该返回一个可选的Void 以反映可选的链接:
let clos = { ()->()? in currentBottle?.jiggle() }
问题详情:
- 您将闭包声明为返回
Void(即->())的闭包。
- 但是,请记住,就像每次使用可选链接一样,整个表达式的返回类型是可选类型。因为如果
currentBottle 确实存在,您的闭包可以返回Void……如果不存在,则返回nil!
所以正确的语法是让你的闭包返回一个Void?(或()?)而不是一个简单的Void
class BottleLayer {
func jiggle() { println("Jiggle Jiggle") }
}
var currentBottle: BottleLayer?
currentBottle?.jiggle() // OK
let clos = { Void->Void? in currentBottle?.jiggle() } // Also OK
let clos = { () -> ()? in currentBottle?.jiggle() } // Still OK (Void and () are synonyms)
注意:如果您让 Swift 为您推断出正确的类型而不是显式强制它,它会为您解决问题:
// Even better: type automatically inferred as ()->()? — also known as Void->Void?
let clos = { currentBottle?.jiggle() }
[编辑]
附加技巧:直接将可选链接分配给变量
您甚至可以将函数直接分配给变量,如下所示:
let clos2 = currentBottle?.jiggle // no parenthesis, we don't want to call the function, just refer to it
请注意,clos2 的类型(此处未明确指定,因此由 Swift 自动推断)在这种情况下 不是 Void->Void? — 即返回 @987654336 的函数@ 或 Void) 与前一种情况一样——但 是 (Void->Void)?,它是“Void->Void 类型的 可选 函数”的类型。 p>
这意味着clos2 本身是“nil 或者是返回 Void 的函数”。要使用它,您可以再次使用可选链接,就像这样:
clos2?()
这将评估为nil,如果clos2 本身是nil(可能是因为currentBottle 本身为零),则不执行任何操作……并执行闭包——因此currentBottle!.jiggle() 代码——并返回Void如果clos2 不为零(可能是因为currentBottle 本身不为零)。
clos2?() 本身的返回类型确实是 Void?,因为它返回 nil 或 Void。
区分Void 和Void? 似乎毫无意义(毕竟,jiggle 函数在这两种情况下都不会返回任何内容),但它可以让你做一些强大的事情,比如在一个if 语句检查调用是否确实发生(并返回 Void 即什么也没有)或没有发生(并返回 nil):
if clos2?() { println("The jiggle function got called after all!") }
[EDIT2] 正如您 (@matt) 自己指出的那样,这种另一种选择还有另一个主要区别:它在表达式受到clos2 影响时评估currentBottle?.jiggle。因此,如果当时currentBottle 是nil,那么clos2 将是nil……即使后来currentBottle 得到了一个非零值。
相反,clos 受到闭包本身的影响,并且可选链接仅在每次调用 clos 时才被评估,因此如果 currentBottle 为 nil,它将评估为 nil...但将评估为非零,如果我们稍后调用 clos() 将调用 jiggle(),此时 currentBottle 变为非零。