2015-04-02 14 views
5

vorrei fare quanto segue in codice swift:Passando e memorizzare le chiusure/callback a Swift

devo chiamare il mio api al fine di aggiornare diversi elementi. Così chiamo l'api per ogni oggetto in modo asincrono. Ogni chiamata API esegue una funzione di callback al termine. Queste richiamate diminuiscono un contatore, in modo che quando il contatore raggiunge 0 so che tutte le chiamate api sono state completate. Quando il contatore raggiunge 0, desidero richiamare una funzione di callback finale (una volta, quando tutte le chiamate sono complete), per aggiornare l'interfaccia utente e così via. Questa callback finale è passata al mio servizio all'inizio e memorizzata in una proprietà di classe per l'esecuzione successiva.

eseguibile Playground fonte:

// Playground - noun: a place where people can play 

class MyService 
{ 
    let api = MyApi() 

    var storedFinalCallback:() -> Void = { arg in } 
    var queue: Int      = 0 

    func update(items: [String], finalCallback:() -> Void) 
    { 
     // Count the necessary API calls 
     queue    = items.count 
     // Store callback for later execution 
     storedFinalCallback = finalCallback 

     for item in items { 
      // Call api per item and pass queueCounter as async callback 
      api.updateCall(item, callback: self.callback()) 
     } 
    } 

    func callback() 
    { 
     queue-- 
     // Execute final callback when queue is empty 
     if queue == 0 { 
      println("Executing final callback") 
      storedFinalCallback() 
     } 
    } 

} 

class MyApi 
{ 
    func updateCall(item: String, callback:()) 
    { 
     println("Updating \(item)") 
    } 
} 

let myItems: [String]  = ["Item1", "Item2", "Item3"] 
let myInstance: MyService = MyService() 

myInstance.update(myItems, finalCallback: {() -> Void in 
    println("Done") 
}) 

Il problema è che con questo codice la richiamata finale si chiama nell'ordine sbagliato. As the console output from the playground shows.

Apparentemente la funzione di callback è già stata eseguita e non è stata trasmessa correttamente. Tuttavia, questo era l'unico modo in cui ero in grado di farlo, senza errori del compilatore.

Qualsiasi aiuto sarebbe davvero apprezzato - Sono rimasto bloccato su questo per due giorni.

+0

Fai i tuoi metodi api.update eseguiti in modo asincrono in parallelo? – Rengers

+0

Sì, lo fanno. Ho pensato che sarebbe stata una buona pratica. – Jan

+0

Se si desidera passare semplicemente la funzione di callback senza eseguirla, rimuovere le due parentesi: 'api.updateCall (item, callback: self.callback)' – Rengers

risposta

5

ho finalmente trovato il codice di lavoro:

// Playground - noun: a place where people can play 

class MyService 
{ 
    let api = MyApi() 

    var storedFinalCallback:() -> Void = { arg in } 
    var queue: Int      = 0 

    func update(items: [String], finalCallback:() -> Void) 
    { 
     // Count the necessary API calls 
     queue    = items.count 
     // Store callback for later execution 
     storedFinalCallback = finalCallback 

     for item in items { 
      // Call api per item and pass queueCounter as async callback 
      api.updateCall(item, callback: self.callback) 
     } 
    } 

    func callback() 
    { 
     queue-- 
     // Execute final callback when queue is empty 
     if queue == 0 { 
      println("Executing final callback") 
      storedFinalCallback() 
     } 
    } 

} 

class MyApi 
{ 
    func updateCall(item: String, callback:() -> Void) 
    { 
     println("Updating \(item)") 
     callback() 
    } 
} 

let myItems: [String]  = ["Item1", "Item2", "Item3"] 
let myInstance: MyService = MyService() 

myInstance.update(myItems, finalCallback: {() -> Void in 
    println("Done") 
})