我发现了这种奇怪的行为:
考虑以下代码:
func foo(_ x: () -> Void) {
}
class Bar {
func bar() {
print("hello")
}
}
var bar: Bar? = Bar()
这些编译:
foo(bar?.bar ?? {})
但这不是:
DispatchQueue.main.async(execute: bar?.bar ?? {})
它产生错误:
无法将类型'()->()'的值转换为预期的参数类型'@convention(block)()->无效'
现在,如果我将bar
更改为:
func bar() -> (() -> Void)? {
return { print("hello") }
}
然后执行:
DispatchQueue.main.async(execute: bar() ?? {})
它可以编译!
所以绝对不是因为??
运算符
问题:您能解释一下这种行为吗?
这是我的实验。
我发现async
方法和foo
之间的唯一区别是execute
参数标有@convention(block)
。
假设::我无法将可选的链接表达式传递到标有@convention(block)
的参数中。
但这似乎是错误的,因为我可以做到,但仍然无法编译:
DispatchQueue.main.async(execute: Bar().bar ?? {})
似乎我也可以将表达式转换为() -> Void
并神奇地进行编译:
DispatchQueue.main.async(execute: (bar?.bar ?? {}) as () -> Void)
bar?.bar ?? {}
是否已经为() -> Void
类型?这没有道理!
另一种编译方法是将bar?.bar
提取为局部变量:
let barFunc = bar?.bar
DispatchQueue.main.async(execute: barFunc ?? {})
这更没有意义...