Дано:
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()
Есть ли способ сделать completion
параметр (и action
) типа, Action?
а также сохранить @escaping
?
Изменение типа приводит к следующей ошибке:
Атрибут @escaping применяется только к типам функций
При удалении @escaping
атрибута код компилируется и запускается, но, по-видимому, он не является правильным, поскольку completion
замыкание выходит за рамки функции.
@escaping
атрибута, код компилируется и работает» - это потому , что, как описано в SR-2444 ,Action?
является, по умолчанию, убегая. Таким образом, удаление@escaping
при использовании дополнительного закрытия завершает то, что вам нужно.Ответы:
Существует отчет SR-2552, который
@escaping
не распознает псевдоним типа функции. вот почему ошибка@escaping attribute only applies to function types
. Вы можете обойти это, расширив тип функции в сигнатуре функции:РЕДАКТИРОВАТЬ 1 :
Я был на самом деле под бета-версии xcode 8, где ошибка SR-2552 еще не была решена. исправляя эту ошибку, представил новую (ту, с которой вы столкнулись), которая все еще открыта. см. SR-2444 .
Обходной путь @Michael Ilseman указал, что временное решение - удалить
@escaping
атрибут из необязательного типа функции, который сохраняет функцию как экранирующую .РЕДАКТИРОВАТЬ 2 :
SR-2444 было закрыто , конкретно указав , что закрытие позиций в параметрах не избежать , и нужно , чтобы они были помечены ,
@escaping
чтобы их избежать, но необязательные параметры будут неявно избежать, так как((Int)->())?
является синонимамиOptional<(Int)->()>
, факультативные закрытия убегают.источник
@escaping may only be applied to parameters of function type func doStuff(stuff: String, completion: (@escaping ()->())?) {
a temporary solution is remove the @escaping attribute from optional function type, that keep the function as escaping.
Можете ли вы объяснить это дальше? Семантика по умолчанию в swift 3 не экранирующая. Хотя он компилируется без @escaping, я боюсь, что это вызовет проблемы, будучи обработанным как неэкранирующий. Это не правда?@autoclosure
? Там одна и та же ошибка ...от: список рассылки swift-users
Поэтому необязательным параметром функции по умолчанию является @escaping.
@noeascape применяется только к параметру функции по умолчанию.
источник
(()->Void)?
- это то же самое, что сказать, что у вас есть,Optional<()->Void>
и для того,Optional
чтобы сохранить право собственности, он должен был бы принимать только@escaping
функции. Я в третьих, что это должен быть принятый ответ. Спасибо.Я столкнулся с подобной проблемой, потому что смешивание
@escaping
и не@escaping
очень сбивает с толку, особенно если вам нужно обойти замыкания.Я закончил тем, что присвоил значение по умолчанию no-op параметру closure через
= { _ in }
, что, я думаю, имеет больше смысла:источник
Я получил его в Swift 3 без каких-либо предупреждений только так:
источник
Важная вещь, которую нужно понять в этом примере, заключается в том, что если вы переходите
Action
кAction?
закрытию, это сбегание. Итак, давайте сделаем то, что вы предлагаете:Хорошо, теперь мы позвоним
doStuff
:Ну, это требование возникает только для избежания замыканий. Так что закрытие ускользает. Вот почему вы не помечаете его как побег - он уже сбежал.
источник