Swift 为什么可以';我是否将某些表达式传递给标记为@conversion(block)的闭包参数?
我发现了这种奇怪的行为: 考虑以下代码:Swift 为什么可以';我是否将某些表达式传递给标记为@conversion(block)的闭包参数?,swift,closures,Swift,Closures,我发现了这种奇怪的行为: 考虑以下代码: func foo(_ x: () -> Void) { } class Bar { func bar() { print("hello") } } var bar: Bar? = Bar() 这些文件汇编如下: foo(bar?.bar ?? {}) DispatchQueue.main.async(execute: (bar?.bar ?? {}) as () -> Void) 但这并不是: Di
func foo(_ x: () -> Void) {
}
class Bar {
func bar() {
print("hello")
}
}
var bar: Bar? = Bar()
这些文件汇编如下:
foo(bar?.bar ?? {})
DispatchQueue.main.async(execute: (bar?.bar ?? {}) as () -> Void)
但这并不是:
DispatchQueue.main.async(execute: bar?.bar ?? {})
它会产生以下错误:
无法将类型“()->()”的值转换为预期的参数类型“@convention(block)(->Void”
现在,如果我将bar
更改为:
func bar() -> (() -> Void)? {
return { print("hello") }
}
然后做:
DispatchQueue.main.async(execute: bar() ?? {})
它编译
所以这肯定不是因为?
操作符
问题:你能解释一下这种行为吗
低于这一点的一切都是我的实验
我发现
async
方法和foo
之间的唯一区别是execute
参数用@约定(块)
标记
假设:我无法将可选链接表达式传递到标有@convention(block)
的参数中
但这似乎是错误的,因为我可以这样做,但它仍然无法编译:
DispatchQueue.main.async(execute: Bar().bar ?? {})
看起来我还可以将表达式转换为()->Void
,它神奇地编译:
foo(bar?.bar ?? {})
DispatchQueue.main.async(execute: (bar?.bar ?? {}) as () -> Void)
是不是bar?.bar??{}
类型已为()->Void
?这毫无意义
另一种编译方法是将bar?.bar
提取为局部变量:
let barFunc = bar?.bar
DispatchQueue.main.async(execute: barFunc ?? {})
这就没什么意义了……不是答案,但它可以引导你找到一些可能有用的东西:我和一个使用“SwiftLint”的大团队一起工作,出于某种原因,当我打算将某个东西声明为
()->(
)时,SwiftLint强迫我将其键入()->Void
!我想知道这是什么原因?应该是一样的吗?!我们已经知道,Void
是()
的类型别名。。。在做了一个快速的调查之后,我发现()->Void
更好地用于匹配Objective-C世界中的返回约定。这可能意味着有一个不同的:)此外,如果你检查一下,我们会注意到-可能出于某种原因-他们只使用()->Void
,而不是()->()
。@AhmadF我怀疑这与()->()
没有转换为()->Void
有关,但是异步(执行:(bar?.bar???{})as()->())
神奇地编译…还有一件有趣的事情是:尽管DispatchQueue.main.async(execute:bar?.bar???{})
产生错误,在常量和pass中声明闭包将使其工作:let closure=bar?.bar???{}DispatchQueue.main.async(execute:closure)
在这一点上,你认为应该报告一个bug还是什么?还是我们遗漏了什么?@AhmadF让我们等一会儿,看看其他人是否知道发生了什么。