Ответ
Определить тип замыкания (escaping/non-escaping) можно, анализируя сигнатуру метода библиотеки и логику его работы.
Основные способы определения:
-
Аннотация
@escaping: Самый прямой признак. Если параметр-замыкание в документации или заголовке API помечен как@escaping, оно является escaping.// Четко указано в сторонней библиотеке public func fetchUserProfile(completion: @escaping (Result<User, Error>) -> Void) -
Анализ контекста вызова (если аннотации нет): Нужно понять, может ли замыкание быть вызвано после возврата из функции. Ключевые индикаторы:
- Замыкание сохраняется в свойство, глобальную переменную или массив.
- Замыкание передается в другую функцию, параметр которой сам является
@escaping(например, вDispatchQueue.async). - Функция запускает асинхронную операцию (сетевой запрос, таймер).
-
Особенность Objective-C API: Все замыкания (blocks), приходящие из Objective-C API, по умолчанию считаются
@escapingв Swift, так как компилятор не может гарантировать их синхронный вызов.
Практический пример анализа:
// Допустим, в документации библиотеки нет @escaping
func processData(with handler: (Data) -> Void)
// Чтобы понять, нужно посмотреть на реализацию или документацию.
// Если в ее теле есть код вида:
// self.storedHandler = handler // Сохранение -> escaping
// DispatchQueue.main.async { handler(data) } // Асинхронный вызов -> escaping
// То замыкание является escaping, даже если аннотации нет.
Рекомендация: Всегда проверяйте документацию. Если сомневаетесь, предполагайте @escaping для асинхронных API и избегайте сильных захватов ([weak self]) в замыканиях, которые могут жить долго.