Come si rende rapida una chiusura opzionale?


93

Sto cercando di dichiarare un argomento in Swift che richiede una chiusura opzionale. La funzione che ho dichiarato si presenta così:

class Promise {

 func then(onFulfilled: ()->(), onReject: ()->()?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }

}

Ma Swift si lamenta del fatto che "il valore limite in un condizionale deve essere un tipo opzionale" dove viene dichiarato "se let".


Considera l'utilizzo di una sola chiusura con parametri.
catanore

Risposte:


113

È necessario racchiudere la chiusura facoltativa tra parentesi. Questo mirerà correttamente ?all'operatore.

func then(onFulfilled: ()->(), onReject: (()->())?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }

Sapete qual è il motivo per doverlo racchiudere tra parentesi?
Marcosc

5
Probabilmente per eliminare l'ambiguità. Se la chiusura facoltativa dovesse avere un valore di ritorno, potrebbe creare confusione sul ()->Int?significato.
Cezar

3
Inoltre, dal libro Swift: "Quando si dichiara un tipo facoltativo, assicurarsi di utilizzare le parentesi per definire correttamente l'ambito? operatore. Ad esempio, per dichiarare un array facoltativo di interi, scrivi l'annotazione del tipo come (Int []) ?; scrivendo Int []? produce un errore. "
Cezar

@Cezar Potresti spiegare un po 'perché e dove usare "Chiusura opzionale", sono curioso di sapere questo.
iLearner

@Cezar Non su un Mac al momento, quindi la mia sintassi potrebbe essere leggermente sbagliata, ma ricorda che in ?realtà è solo zucchero per Optional<T>, quindi potresti anche scrivere `func then (onFulfilled: () -> (), onReject: Optional <() -> ()>) {`allora non avresti bisogno dell'extra (), anche se IMO ()?è più carino. Inoltre puoi renderlo ancora più carino con un typealias come typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Andrew Carter,

62

Per rendere il codice ancora più breve possiamo usare nilcome valore predefinito per il onRejectparametro e il concatenamento opzionale ?()quando lo chiamiamo:

func then(onFulfilled: ()->(), onReject: (()->())? = nil) {
  onReject?()
}

In questo modo possiamo omettere il onRejectparametro quando chiamiamo thenfunzione.

then({ /* on fulfilled */ })

Possiamo anche usare la sintassi di chiusura finale per passare il onRejectparametro alla thenfunzione:

then({ /* on fulfilled */ }) {
  // ... on reject
}

Ecco un post sul blog a riguardo.


34

Dato che presumo che questa chiusura "opzionale" non debba semplicemente fare nulla, potresti usare un parametro con una chiusura vuota come valore predefinito:

func then(onFulfilled: ()->(), onReject: ()->() = {}){       
    // now you can call your closures
    onFulfilled()
    onReject()
}

questa funzione può ora essere chiamata con o senza la onRejectrichiamata

then({ ... })
then({ ... }, onReject: { ... })

Non c'è bisogno che Swift sia fantastico Optionals?qui!


Questa è una bella soluzione!
Roland T.

6

Forse è un modo più pulito. Specialmente quando la chiusura ha parametri complicati.

typealias SimpleCallBack = () -> ()

class Promise {

func then(onFulfilled: SimpleCallBack, onReject: SimpleCallBack?){       
    if let callableRjector = onReject {
        // do stuff! 
    }
}

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.