Как добавить аннотацию @noescape к необязательному закрытию

Моя функция имеет эту подпись:

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

Можно ли использовать его в необязательных параметрах?

Ответ 1

Требования

Если ваши требования следующие:

  • Параметр baz является closure
  • Параметр baz помечен @noescape (потому что вы хотите опустить self в код замыкания)
  • параметр baz может быть опущен во время вызова foo

Решение

Затем вы можете использовать следующий синтаксис

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

}

Как вы можете видеть, основное отличие от вашего кода заключается в следующем:

  • здесь baz не является optional type (но это "необязательный параметр" )
  • а его значение по умолчанию - empty closure не a 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 требует закрытия с 1 параметром типа String и возвращаемым значением типа Int. Как вы можете видеть, я добавил значение по умолчанию для параметра, закрытие которого возвращает 0. Обратите внимание, что закрытие по умолчанию никогда не будет использоваться, поэтому вы можете заменить 0 на любое Int значение, которое вы хотите.

Теперь вы можете решить, следует ли использовать ваше закрытие для параметра baz param

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")
    }
}