我在理解匿名闭包参数的使用方面遇到了一些麻烦。为了说明我在操场上掀起了这个人为的例子:
typealias SomeClosureType = (
thing0: Float,
thing1: Float,
thing2: Float,
thing3: Float,
thing4: Float,
thing5: Float
) -> Void
class MyClass {
var someClosure: SomeClosureType!
init() {
// This is OK but long
self.someClosure = { (thing0: Float, thing1: Float, thing2: Float, thing3: Float, thing4: Float, thing5: Float) in self.handleThing0(thing0) }
// Compiler error: "cannot assign value of type '(Float) -> ()' to type 'SomeClosureType!'"
self.someClosure = { self.handleThing0($0) }
}
func handleThing0(thing0: Float) {
print("\(thing0)")
}
}
let myInstance = MyClass()
myInstance.someClosure(thing0: 0, thing1: 1, thing2: 2, thing3: 3, thing4: 4, thing5: 5)
所以基本上当我尝试从闭包中访问匿名闭包参数时,我得到了这个错误。我错过了什么?
答案 0 :(得分:3)
对于编译器来说,看起来你的闭包只处理一个float参数,因为你的闭包永远不会以任何方式引用其他5个“东西”。因此存在明显的不匹配,并且编译器将其标记为错误。
如果以任何有效方式引用所有6个输入参数,则错误将消失。例如,虽然这不是你应该写的东西,但仅仅引用这样的附加参数是有效的:
self.someClosure = { self.handleThing0($0); _ = [$1,$2,$3,$4,$5] }
表达目标的最短/最佳方式是:
self.someClosure = { thing0, _, _, _, _, _ in self.handleThing0(thing0) }
其中每个_
表示您忽略的值,但编译器可以推断它们将是Float值。
答案 1 :(得分:2)
这个具体问题会定期出现在迅速演变中。克里斯拉特纳说this is considered a bug in the compiler, but it requires significant effort to fix:
2016年5月13日上午9:16,Joe Groff通过快速进化 swift.org>写道:
这鼓励在可选的封闭物上使用空的封闭物,我认为这是有争议的。一般来说,我尽量避免选择 当它们可以用非可选值精确替换时。 此外,大多数Cocoa完成处理程序都不是可选的。
另一种方法是不这样做,但鼓励任何合理地为空的闭包实际上都是可选的。我会 然后想要导入带有void返回闭包的Cocoa函数 作为避免“{_ in}”的选项。
1。一般来说,我认为我们应该允许隐式参数,而不要求闭包像我们一样使用所有隐式$ n变量 今天。这些都应该是有效的:
let _: () -> () = {}
let _: (Int) -> () = {}
let _: (Int, Int) -> Int = { 5 }
let _: (Int, Int) -> Int = { $0 }
let _: (Int, Int) -> Int = { $1 }
我同意,但我认为这是编译器中的一个明显错误。一世 不认为它需要一个提案。
不幸的是,修复它是非常重要的......
-Chris
在修复发生之前,你会遇到第一个表单。
答案 2 :(得分:0)
我不是100%肯定你在这里想做什么,但我会试着提供一些信息。对于顶部(长的),这实际上是正确的。所以闭包只是真正的功能,设计得更紧凑,就像你当前范围内的小块代码一样。如果您只打算使用thing0属性,那么您可以使用_忽略其余部分,例如:
self.someClosure = { thing0, _ in
self.handleThing0(thing0)
}
虽然使用闭包时需要小心,因为ARC很容易开始获得保留周期。
答案 3 :(得分:0)
在你的第二个闭包中你只使用$0
所以编译器假设你的匿名闭包只需要一个参数,考虑到handleThing0()
,(Float) -> ()
的签名,然后编译器知道封闭的签名是(Float) -> ()
,因为$0
被传递给handleThing0()
,但不返回任何内容。
然后尝试将(Float) -> ()
闭包分配给类型为(Float, Float, Float, Float, Float, Float) -> Void
的属性,这是不可能的,因为闭包采用小于请求的5参数,因此出错。