为什么不能将某些表达式传递给标记为@convetion(block)的闭包参数?

时间:2019-01-17 07:15:44

标签: 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 ?? {})

它产生错误:

  

无法将类型'()->()'的值转换为预期的参数类型'@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 ?? {})

这更没有意义...

0 个答案:

没有答案