Sobes.tech
Middle

Explica diferența dintre closures de escaping și non-escaping și în ce cazuri este necesar să folosiți @escaping.

sobes.tech AI

Răspuns de la AI

În mod implicit, închiderile sunt non-escaping.

Chiar închidere non-escaping:

  • Se execută în corpul funcției în care este transmisă.
  • Capturează variabile, dar le eliberează după finalizarea funcției.
  • Nu supraviețuiește funcției.
func doSomething(completion: () -> Void) {
    // Apelarea completion aici
    completion() 
}

Chiar închidere escapable:

  • Se execută după ce funcția în care este transmisă se întoarce.
  • Supraviețuiește corpului funcției.
  • Poate fi stocată pentru execuție ulterioară, de exemplu, într-un alt fir sau asincron.
  • Capturează variabile, păstrând referințe puternice, ceea ce poate duce la cicluri de referințe puternice (retention cycles). Necesită declarație explicită @escaping.
class DataManager {
    var completionHandlers: [() -> Void] = []

    func addCompletionHandler(handler: @escaping () -> Void) {
        completionHandlers.append(handler)
    }

    func performTasks() {
        // Executarea sarcinilor...
        for handler in completionHandlers {
            handler() // Apelarea handler-urilor mai târziu
        }
    }
}

Utilizarea @escaping este necesară în următoarele cazuri:

  • Când închiderea este stocată într-o proprietate a unei clase sau structuri.
  • Când închiderea este transmisă către alt fir sau operație asincronă (de exemplu, solicitare de rețea, GCD, OperationQueue).
  • Când închiderea este utilizată ca handler de eveniment sau delegat.