如何将@noescape 注释添加到可选闭包

Posted

技术标签:

【中文标题】如何将@noescape 注释添加到可选闭包【英文标题】:How to add @noescape annotation to optional closure 【发布时间】:2015-11-18 12:13:42 【问题描述】:

我的函数有这个签名:

func foo(bar: String, baz: ((String) -> ())? = nil)

现在我想让self 在给定的闭包内转义。 但是当我尝试这个时:

func foo(bar: String, @noescape baz: ((String) -> ())? = nil)

编译器抱怨:

@noescape may only be applied to parameters of function type

是否可以在可选参数中使用它?

【问题讨论】:

它不能与可选功能一起使用。如果您删除 ? = nil 它可以工作。 感谢您的快速回复,我知道删除? = nil 有效,让我们看看是否有人有不同的想法 我的编译器也抱怨。我可以知道,你为什么需要这个?我认为 noescape 告诉“执行完成后保证不需要它”。可选意味着该值存在于两种不同的状态。如果将 nil 设置为可选值,则仍然存在一些对其的引用。如果闭包是可选的,则闭包可以为零,但仍然存在对它的引用。 noescape 似乎更像是“临时的”......非常有趣的问题! 我希望能够向foo 发送或不发送闭包,但如果我这样做了,我不想在我的闭包中使用self.。是的,闭包不会被异步存储或调用 我也有这个问题,不明白为什么不能将@noescape 添加到可选闭包中(除非语言设计者还没有解决这个问题)。 【参考方案1】:

要求

如果您的要求如下:

baz 参数是closure baz 参数标有@noescape(因为你想在闭包代码中省略selfbaz 参数在调用foo 期间可以省略

解决方案

那么你可以使用下面的语法

func foo(bar: String, @noescape baz: ((String) -> ()) =  _ in  ) 


如您所见,与您的代码的主要区别在于:

这里的baz 不是optional type(但它是一个“可选参数”) 其默认值为empty closure 而不是nil 值。

示例

根据您的要求,您现在可以将闭包传递给baz,而无需使用self

class Boo 
    let world = "world"
    func boo() 
        foo("hello")  (something) -> () in
            print(world)
        
    

你也可以省略baz参数

class Boo 
    let world = "world"
    func boo() 
        foo("hello")
    

更新:使用返回类型不同于 Void 的闭包

在下面的评论中,用户 TadeasKriz 询问了如何将这种方法与返回值与 Void 不同的闭包一起使用。

这就是解决方案

func foo(bar: String, @noescape baz: ((String) -> (Int)) =  _ in return 0  ) 


这里的baz 参数确实需要一个带有String 类型的1 个参数和Int 类型的返回值的闭包。 如您所见,我为参数添加了一个默认值,一个确实返回0 的闭包。请注意,将永远不会使用默认闭包,因此您可以将 0 替换为您想要的任何 Int 值。

现在您可以决定是否使用将您的闭包传递给baz 参数

class Boo 
    let world = "world"
    func boo() 
        foo("hello")  (something) -> Int in
            print(world)
            return 100
        
    

或者,同样,您可以完全省略 baz 参数。

class Boo 
    let world = "world"
    func boo() 
        foo("hello")
    

【讨论】:

很棒的解决方法,而 Swift 不允许“正确的方式” 不幸的是,当闭包的返回类型不是 Void 时,它没有帮助。 例如:func foo(bar: String, @noescape baz: (String -> MyAwesomeType) = _ in ) . 我最终解决了这个问题:func foo(bar: String, @noescape baz: (String -> MyAwesomeType?) = _ in nil ) @TadeasKriz:我为我的答案添加了更新。现在您可以使用返回类型不同于Void 的闭包。

以上是关于如何将@noescape 注释添加到可选闭包的主要内容,如果未能解决你的问题,请参考以下文章

swift3.0 逃逸的“闭包”

Swift 1.2 中的 @noescape 属性

如何加到可选Kernel中?(jupyter notebook)

莫名其妙的标记之@noescape

Swift 中的可选闭包属性

使用 SQLX 转到可选字段