Sobes.tech
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.