【问题标题】:How to add @noescape annotation to optional closure如何将@noescape 注释添加到可选闭包
【发布时间】: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 添加到可选闭包中(除非语言设计者还没有解决这个问题)。

标签: ios swift closures


【解决方案1】:

要求

如果您的要求如下:

  • baz 参数是closure
  • baz 参数标有@noescape(因为你想在闭包代码中省略self
  • baz 参数在调用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 的闭包。
猜你喜欢
  • 2018-02-24
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 2017-04-28
  • 2012-08-24
  • 2016-01-26
  • 1970-01-01
相关资源
最近更新 更多