Swift 3中非逃逸闭包的问题

4

我有一个以以下形式表示的 Array 扩展:

extension Array
{
    private func someFunction(someClosure: (() -> Int)?)
    {
        // Do Something
    }

    func someOtherFunction(someOtherClosure: () -> Int)
    {
        someFunction(someClosure: someOtherClosure)
    }
}

但我遇到了错误:将非逃逸参数“someOtherClosure”传递给需要@escaping闭包的函数
两个闭包确实都是非逃逸的(默认情况下),并且在someFunction中显式添加@noescape会产生警告,表明这是Swift 3.1中的默认设置。
你有什么想法为什么会出现这个错误?
-- 更新 -- 附带截图: enter image description here

你没有在someOtherFunction()内调用someOtherClosure(), 所以它不应该是一个逃逸闭包吗?Swift不是我的主要语言。 - user3476154
@Lu_ 添加了截图 - XmasRights
func someOtherFunction(someOtherClosure: @escaping () -> Int) - Laura Calinoiu
使用修复功能:单击圆圈,将提供一个修复建议。 - Laura Calinoiu
请见 https://oleb.net/blog/2016/10/optional-non-escaping-closures/。 - Martin R
显示剩余2条评论
3个回答

6

可选闭包始终是逃逸闭包。

为什么呢?因为可选项(它是一个枚举)包装了闭包并在内部保存它。

这里有一篇关于 @escaping 的怪异之处的优秀文章,可以在此处阅读。


太棒了!谢谢。 - XmasRights

5
正如已经提到的,Optional闭包是escaping的。还有一个补充: Swift 3.1提供了一个withoutActuallyEscaping辅助函数,可以在这里很有用。它仅标记传递闭包内部使用的闭包为escaping,因此您不必将escaping属性暴露给函数签名。 可以像这样使用:
extension Array {

    private func someFunction(someClosure: (() -> Int)?) {
        someClosure?()
    }

    func someOtherFunction(someOtherClosure: () -> Int) {
        withoutActuallyEscaping(someOtherClosure) {
            someFunction(someClosure: $0)
        }
    }
}


let x = [1, 2, 3]

x.someOtherFunction(someOtherClosure: { return 1 })

希望这对您有所帮助!

0
问题在于可选项(在这种情况下为(()-> Int)?)是一个枚举,它捕获了它们的值。如果该值是一个函数,则必须使用@escaping,因为它确实被可选项所捕获。在您的情况下,它变得棘手,因为可选项捕获的闭包自动捕获另一个闭包。因此,someOtherClosure 也必须标记为@escaping
您可以在playground中测试以下代码以确认此内容:
extension Array
{
    private func someFunction(someClosure: () -> Int)
    {
        // Do Something
    }

    func someOtherFunction(someOtherClosure: () -> Int)
    {
        someFunction(someClosure: someOtherClosure)
    }
}

let f: ()->Int = { return 42 }

[].someOtherFunction(someOtherClosure: f)   

1
Optional并不是不透明的 - 它是一个enum,完全透明。 - Hamish
1
如@Hamish所说,可选项是枚举 Optional<T> { case some(T), case none }。当您记住这一点时,许多可选项的“怪癖”就变得清晰了。 - JeremyP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接