对成员'的模糊引用;打印';-(范围在Swift关闭范围内?)

对成员'的模糊引用;打印';-(范围在Swift关闭范围内?),swift,closures,Swift,Closures,这包括: let s = SignalsService() s.addListener( "key", callback: { a, b in print( "success" ) } ) 这并不是: let s = SignalsService() let cb = { a, b in print( "success" ) } s.addListener( "key", callback: cb ) 在let cb=…行将错误不明确引用抛出到成员“print” 那为什么呢?在 s.addL

这包括:

let s = SignalsService()
s.addListener( "key", callback: { a, b in print( "success" ) } )
这并不是:

let s = SignalsService()
let cb = { a, b in print( "success" ) }
s.addListener( "key", callback: cb )
let cb=…
行将错误
不明确引用抛出到成员“print”

那为什么呢?

s.addListener( "key", callback: { a, b in print( "success" ) } )
编译器可以从上下文推断闭包的类型, i、 e.从
addListener()
方法的类型。如果这个方法是 例如,声明为

func addListener(key : String, callback: (Int, Int) -> Void)
然后编译器可以推断参数

{ a, b in print( "success" )
是一个包含两个
Int
参数并返回
Void
的闭包

没有这样的上下文,因此编译器无法知道 闭包的类型。返回类型可以推断为
Void
因为闭包由单个表达式组成, 但您必须指定参数的类型,例如

let cb = { (a : Int, b : Int) in print( "success" ) }

扩展@MartinR的优秀答案

Swift需要能够推断出
cb
的类型为
(Int,Int)->()
,或者您可以显式设置类型:

let cb: (Int, Int)->() = { a, b in print( "success" ) }
然后您可能会注意到
a
b
未使用,并用
替换它们:

let cb: (Int, Int)->() = { _ in print( "success" ) }
当函数有两个参数时,为什么我们可以只使用一个
?在这种情况下,Swift知道有两个参数,因此
\uuu
将取代包含所有参数的元组。它取代了
(u,u)


您可以将
\uu
与@MartinR的答案结合使用:

let cb = { (_:Int, _:Int) in print( "success" ) }
或者你可以这样写:

let cb = { (_:(Int, Int)) in print( "success" ) }
可理解为:

cb
接受两个类型为
Int
的参数,它会忽略并打印这两个参数 “成功”


此外,当回调函数应该返回一个值,但您尚未在闭包中键入
返回值时,您会遇到此错误。。。
let cb = { (_:(Int, Int)) in print( "success" ) }