Будет ли ошибка при передаче non-escaping closure дальше и почему?
Что проверяют
Понимаете ли вы, что non-escaping это гарантия компилятору, а не просто атрибут в сигнатуре. Ждут точного ответа, когда ошибка будет, а когда нет, и следом спрашивают, зачем Swift делает замыкания неубегающими по умолчанию.
Как отвечать
Начните с правила: со Swift 3 параметр-замыкание по умолчанию non-escaping, то есть вызывается только до возврата из функции. Дальше три случая:
- передача в другой non-escaping параметр: ошибки нет. Гарантия сохраняется по цепочке, компилятор это видит;
- передача в
@escapingпараметр: ошибка компиляции «Passing non-escaping parameter to function expecting an @escaping closure». Типичный пример: отдать замыкание вDispatchQueue.main.asyncили вTask { }; - сохранение или захват: присвоить параметр свойству или захватить его внутри escaping-замыкания тоже нельзя, компилятор скажет, что escaping-замыкание захватывает non-escaping параметр.
Почему так: про non-escaping замыкание компилятор знает, что оно не переживёт вызов. Контекст можно разместить на стеке, лишние retain/release не нужны, а внутри можно обращаться к свойствам без явного self., ведь цикла удержания не возникнет.
Как исправить: если замыкание действительно живёт дольше функции, пометьте параметр @escaping и подумайте про [weak self] на вызывающей стороне. Если API требует escaping, а вы знаете, что работа закончится до возврата (например, ленивый filter внутри функции), есть withoutActuallyEscaping(_:do:): он даёт временную escaping-копию и в рантайме проверяет, что она не утекла.
Где спотыкаются
Отвечают «ошибка будет всегда». Передача non-escaping замыкания в non-escaping параметр допустима, и как раз эту деталь и проверяют.
Забывают, что опциональное замыкание (() -> Void)? неявно escaping. Писать к нему @escaping не нужно и нельзя, а удерживается оно как любое escaping-замыкание, со всеми рисками циклов.
Лечат ошибку, навешивая @escaping на все параметры подряд. Так теряются оптимизации, а в местах, где цикла удержания быть не могло, появляется необходимость думать про weak self.