Middle
Wyjaśnij różnicę między closures escaping a non-escaping oraz w jakich przypadkach należy używać @escaping.
sobes.tech AI
Odpowiedź od AI
Domyślne zamknięcia są nie-escapujące.
Nie-escapujące zamknięcie:
- Wykonuje się w ciele funkcji, do której jest przekazywane.
- Przechwytuje zmienne, ale zwalnia je po zakończeniu funkcji.
- Nie przetrwa funkcji.
func doSomething(completion: () -> Void) {
// Wywołanie completion tutaj
completion()
}
Escapujące zamknięcie:
- Wykonuje się po zwróceniu funkcji, do której jest przekazywane.
- Przetrwa ciało funkcji.
- Może być przechowywane do późniejszego wykonania, np. w innym wątku lub asynchronicznie.
- Przechwytuje zmienne, zachowując silne odniesienia, co może prowadzić do cykli silnych odniesień (retain cycles). Wymaga jawnego zadeklarowania
@escaping.
class DataManager {
var completionHandlers: [() -> Void] = []
func addCompletionHandler(handler: @escaping () -> Void) {
completionHandlers.append(handler)
}
func performTasks() {
// Wykonywanie zadań...
for handler in completionHandlers {
handler() // Wywołanie handlerów później
}
}
}
Użycie @escaping jest konieczne w następujących przypadkach:
- Gdy zamknięcie jest przechowywane w właściwości klasy lub struktury.
- Gdy zamknięcie jest przekazywane do innego wątku lub operacji asynchronicznej (np. żądanie sieciowe, GCD, OperationQueue).
- Gdy zamknięcie jest używane jako obsługa zdarzeń lub delegat.