2014-09-21 5 views
7

Ho difficoltà a capire un problema che sto riscontrando. Per semplificare, userò il metodo UIView. In sostanza, se scrivo il metodoBlocco di completamento Swift

UIView.animateWithDuration(1, animations: {() in 
     }, completion:{(Bool) in 
      println("test") 
    }) 

funziona benissimo. Ora, se faccio lo stesso metodo, ma la creazione di una stringa in questo modo:

UIView.animateWithDuration(1, animations: {() in 
     }, completion:{(Bool) in 
      String(23) 
    }) 

smette di funzionare. Errore del compilatore: Argomento mancante per il parametro "ritardo" nella chiamata

Ora, ecco la parte strana. Se io faccio lo stesso codice esatto di quello che non riesce, ma basta aggiungere un comando di stampa in questo modo:

UIView.animateWithDuration(1, animations: {() in 
     }, completion:{(Bool) in 
      String(23) 
      println("test") 
    }) 

inizia a lavorare di nuovo.

Il mio problema è fondamentalmente la stessa cosa. Il mio codice:

downloadImage(filePath, url: url) {() -> Void in 
     self.delegate?.imageDownloader(self, posterPath: posterPath) 
     } 

Non funziona. Ma se io cambio.

downloadImage(filePath, url: url) {() -> Void in 
      self.delegate?.imageDownloader(self, posterPath: posterPath) 
       println("test") 
      } 

o anche:

downloadImage(filePath, url: url) {() -> Void in 
      self.delegate?.imageDownloader(self, posterPath: posterPath) 
      self.delegate?.imageDownloader(self, posterPath: posterPath) 
      } 

funziona benissimo. Non riesco a capire perché questo sta accadendo. Sono vicino ad accettare che si tratta di un bug del compilatore.

risposta

10

chiusure a Swift hanno implicit returns quando vengono fatte solo da una singola espressione . Ciò consentirà per il codice succinta come questo:

reversed = sorted(names, { s1, s2 in s1 > s2 }) 

Nel tuo caso, quando si crea la stringa qui:

UIView.animateWithDuration(1, animations: {() in }, completion:{(Bool) in 
    String(23) 
}) 

si finisce per tornare quella stringa e che rende la firma del vostro chiusura:

(Bool) -> String 

che non corrisponde più ciò che è richiesto da animateWithDuration 's firma (che si traduce in errore criptico Missing argument for parameter 'delay' in call di Swift perché non può fi e una firma appropriata da abbinare).

Una soluzione semplice è quella di aggiungere un return vuota alla fine della vostra chiusura:

UIView.animateWithDuration(1, animations: {() in}, completion:{(Bool) in 
    String(23) 
    return 
}) 

Il che rende la vostra firma quello che dovrebbe essere:

(Bool) ->() 

Il tuo ultimo esempio:

downloadImage(filePath, url: url) {() -> Void in 
    self.delegate?.imageDownloader(self, posterPath: posterPath) 
    self.delegate?.imageDownloader(self, posterPath: posterPath) 
} 

funziona perché ci sono due espressioni lì, non solo una; i ritorni impliciti avvengono solo quando la chiusura contiene una singola espressione. Quindi, quella chiusura non restituisce nulla e corrisponde alla sua firma.

+0

Grazie. Ma perché non fallisce se aggiungo String (23) e copiamo di nuovo la stessa riga come: String (23); Stringa (23); ? – Wak

+0

In realtà ero nel bel mezzo di chiarire che nella risposta. Vedi modifica. –

+0

Grazie per questa risposta; mi ha aiutato a capire perché ho avuto uno strano "non posso invocare 'animateWithDuration' con un elenco di argomenti di tipo ..." errore. La soluzione è stata esattamente la stessa. – SonarJetLens