2016-03-27 40 views
6

Sto leggendo il manuale del linguaggio di programmazione Swift e menziona una chiusura di escape. Per quanto riguarda le chiusure in fuga, non so cosa intendano con "la chiusura viene passata come argomento alla funzione, ma viene chiamata dopo che la funzione ritorna". Qualcuno potrebbe fornire un esempio su chiusure di fuga?Qual è un buon esempio di chiusura di una fuga in Swift?

risposta

2

Un esempio di una chiusura in fuga sarebbe il gestore di completamento in qualche operazione asincrona, come ad esempio l'avvio di una richiesta di rete:

func performRequest(parameters: [String: String], completionHandler: (NSData?, NSError?) ->()) { 
    let request = NSMutableURLRequest(URL: url) 
    request.HTTPMethod = "POST" 
    request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: []) 
    request.setValue("application/json", forHTTPHeaderField: "Content-Type") 

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in 
     completionHandler(data, error) 
    } 
    task.resume() 
} 

e questo è chiamato in questo modo:

performRequest(["foo" : "bar"]) { data, error in 
    guard error == nil else { 
     print(error) 
     return 
    } 

    // now use data here 
} 

// Note: The `completionHandler` above runs asynchronously, so we 
// get here before the closure is called, so don't try to do anything 
// here with `data` or `error`. Any processing of those two variables 
// must be put _inside_ the closure above. 

Questo completionHandler chiusura è considerata come fuga in quanto il metodo NSURLSessiondataTaskWithRequest viene eseguito in modo asincrono (ovvero restituisce immediatamente e la sua chiusura verrà richiamata in seguito al termine della richiesta).

2

In Swift 3 i parametri di chiusura diventano senza escape per impostazione predefinita.

Abbiamo bisogno di scrivere l'attributo @escaping prima del tipo di parametri per indicare che la chiusura viene chiamata dopo che la funzione è tornata.

typealias Operation = (Data?) ->() 

func addToQueue(data: Data?, operation: @escaping Operation) { 
    OperationQueue.main.addOperation { 
     operation(data) 
    } 
} 

Se togliamo attributo @escaping, Xcode mostrerà il seguente messaggio di errore

non-escaping parameter error message

+0

risposta Abbastanza chiaro, ha aiutato a capire dove era il mio problema. Avevo 3-4 livelli di chiusura, quindi era difficile capire dove esattamente "@ escaping" dovrebbe essere posizionato. – Jonauz