Middle
Обяснете разликата между escaping и non-escaping closures и в кои случаи е необходимо да използвате @escaping.
sobes.tech AI
Отговор от AI
По подразбиране, затварящите се блокове са non-escaping.
Non-escaping затваряне:
- Изпълнява се в тялото на функцията, към която се предава.
- Засмуква променливи, но ги освобождава след приключване на функцията.
- Не оцеляват функцията.
func doSomething(completion: () -> Void) {
// Викаме completion тук
completion()
}
Escaping затваряне:
- Изпълнява се след връщането от функцията, към която се предава.
- Оцеляват след тялото на функцията.
- Могат да бъдат запазени за по-късно изпълнение, например в друг поток или асинхронно.
- Засмуква променливи, запазвайки силни препратки, което може да доведе до цикли на силни препратки (retain cycles). Изисква явна декларация
@escaping.
class DataManager {
var completionHandlers: [() -> Void] = []
func addCompletionHandler(handler: @escaping () -> Void) {
completionHandlers.append(handler)
}
func performTasks() {
// Изпълнение на задачи...
for handler in completionHandlers {
handler() // По-късно извикване
}
}
}
Използването на @escaping е необходимо в следните случаи:
- Когато затварянето се запазва като свойство на клас или структура.
- Когато затварянето се предава към друг поток или асинхронна операция (например, мрежов заявка, GCD, OperationQueue).
- Когато затварянето се използва като обработчик на събития или делегат.