0Pricing
Swift Academy · Lezione

Closure escaping

Conservi closure che sopravvivono alla funzione che le ha create.

Closure escaping è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.

Escaping e non-escaping

Per impostazione predefinita, un parametro closure è non-escaping: deve essere chiamato prima che la funzione restituisca il controllo. Lo contrassegni con @escaping se può essere memorizzato e chiamato in un secondo momento.

Una closure non-escaping

Questa closure viene eseguita in modo sincrono e non esiste più quando la funzione restituisce il controllo:

func run(_ work: () -> Void) {
    work()
}
run { print("done now") }  // "done now"

Perché serve @escaping

Memorizzare una closure per usarla in seguito richiede @escaping:

var handlers: [() -> Void] = []
func register(_ handler: @escaping () -> Void) {
    handlers.append(handler)  // escapes the function
}
register { print("later") }
handlers[0]()  // "later"

Escaping con lavoro asincrono

Gli handler di completamento sono escaping perché vengono eseguiti dopo la restituzione della funzione:

func load(then completion: @escaping (String) -> Void) {
    // imagine async work
    completion("data")
}
load { result in print(result) }  // "data"

self deve essere esplicito

All'interno di una closure escaping deve scrivere self. in modo esplicito quando accede ai membri dell'istanza — un promemoria del fatto che la closure potrebbe mantenere self.

self esplicito nelle closure escaping

Il compilatore richiede il riferimento esplicito:

class Loader {
    var name = "L"
    func start(_ done: @escaping () -> Void) {
        let cb = { print(self.name); done() }
        cb()
    }
}
Loader().start { print("finished") }  // "L" then "finished"

Memorizzare molti callback

Le closure escaping permettono di creare liste di osservatori:

class Emitter {
    private var listeners: [(Int) -> Void] = []
    func on(_ l: @escaping (Int) -> Void) { listeners.append(l) }
    func fire(_ v: Int) { listeners.forEach { $0(v) } }
}
let e = Emitter()
e.on { print("got \($0)") }
e.fire(7)  // "got 7"

Restituire una closure memorizzata

Le closure conservate nelle proprietà sono escaping:

class Button {
    var action: (() -> Void)?
    func setAction(_ a: @escaping () -> Void) { action = a }
}
let b = Button()
b.setAction { print("tapped") }
b.action?()  // "tapped"

Le closure opzionali sono escaping

Un parametro closure opzionale è implicitamente escaping (è racchiuso in Optional), quindi può essere memorizzato:

func maybe(_ f: (() -> Void)?) {
    f?()
}
maybe { print("ran") }  // "ran"

Escaping in un array di attività

Una coda di attività differite è un caso d'uso classico di escaping — ogni closure viene memorizzata e poi eseguita in un secondo momento:

var tasks: [() -> Int] = []
func schedule(_ task: @escaping () -> Int) {
    tasks.append(task)
}
schedule { 1 + 1 }
schedule { 10 * 2 }
print(tasks.map { $0() })  // [2, 20]

Nota sulle prestazioni

Le closure non-escaping possono essere ottimizzate in modo più aggressivo (non è necessaria un'allocazione nell'heap). Mantenga le closure non-escaping quando possibile; le renda escaping solo quando deve realmente memorizzarle o rimandarne l'esecuzione.

func sum(_ xs: [Int], _ f: (Int) -> Int) -> Int {
    xs.reduce(0) { $0 + f($1) }   // non-escaping, fast
}
print(sum([1, 2, 3]) { $0 * $0 })  // 14

Verifica rapida

Quando è necessario contrassegnare un parametro closure con @escaping?

Riepilogo

Ha imparato a conoscere le closure escaping:

  • Non-escaping è il comportamento predefinito; le closure vengono eseguite prima che la funzione restituisca il controllo
  • @escaping è necessario per memorizzare o rimandare l'esecuzione di una closure
  • Le closure escaping richiedono l'accesso esplicito a self.
  • I parametri closure opzionali sono implicitamente escaping; preferisca non-escaping per ottenere prestazioni migliori

Prossimo argomento: capture list e weak self.

Domande Frequenti

La lezione «Closure escaping» è gratuita?

Sì — il testo completo di «Closure escaping» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.

Cosa imparerò in «Closure escaping»?

Conservi closure che sopravvivono alla funzione che le ha create. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Swift Academy?

Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Closure escaping»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Swift Academy?

Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Cattura dei valori per riferimento
  2. Closure escaping
  3. Liste di cattura e weak self
  4. Autoclosure
← Torna a Swift Academy