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 }) // 14Verifica 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.