Swift 3 необязательный параметр экранирования закрытия


дано:

typealias Action = () -> ()

var action: Action = { }

func doStuff(stuff: String, completion: @escaping Action) {
    print(stuff)
    action = completion
    completion()
}

func doStuffAgain() {
    print("again")
    action()
}

doStuff(stuff: "do stuff") { 
    print("swift 3!")
}

doStuffAgain()

есть ли способ сделать

4 114

4 ответа:

есть SR-2552 сообщаю об этом @escaping не распознает псевдоним типа функции. вот почему ошибка @escaping attribute only applies to function types. вы можете обойти эту проблему, развернув тип функции в сигнатуре функции:

typealias Action = () -> ()

var action: Action? = { }

func doStuff(stuff: String, completion: (@escaping ()->())?) {
    print(stuff)
    action = completion
    completion?()
}

func doStuffAgain() {
    print("again")
    action?()
}

doStuff(stuff: "do stuff") {
    print("swift 3!")
}

doStuffAgain()

EDIT::

Я был на самом деле под бета-версией xcode 8, где ошибка SR-2552 еще не решено. исправив эту ошибку, ввел новый (тот, с которым вы столкнулись), который все еще открыт. видеть SR-2444.

решение Михаил Ilseman указано как временное решение удалить @escaping атрибут из необязательного типа функции,что сохранить функцию как побег.

func doStuff(stuff: String, completion: Action?) {...}

от: swift-список рассылки пользователей

в принципе, @escaping допустим только на замыканиях в позиции параметра функции. Правило noescape-by-default применяется только к этим замыканиям в позиции параметра функции, в противном случае они экранируются. Агрегаты, такие как перечисления со связанными значениями (например, необязательные), кортежи, структуры и т. д., если они имеют замыкания, следуйте правилам по умолчанию для замыканий, которые не находятся в положении параметра функции, т. е. они убегающий.

поэтому необязательным параметром функции является @escaping по умолчанию.
@noeascape применяется только к параметру функции по умолчанию.

Я получил его работу в Swift 3 без каких-либо предупреждений только таким образом:

func doStuff(stuff: String, completion: (()->())? ) {
    print(stuff)
    action = completion
    completion?()
}

я сталкиваюсь с подобной проблемой и потому, что смешивание @escaping и non @escaping очень запутанно, особенно если вам нужно передать закрытие. Я в конечном итоге с параметрами по умолчанию (который я думаю, имеет больше смысла)

func doStuff(stuff: String = "do stuff",
        completion: @escaping (_ some: String) -> Void = { _ in }) {
     completion(stuff)
}

doStuff(stuff: "bla") {
    stuff in
    print(stuff)
}

doStuff() {
    stuff in
    print(stuff)
}