2015-04-09 20 views
6

Uso le chiusure opzionali, ma non riesco a trovare il modo di trasmettere un parametro. Cercati ovunque, ho provato tutti i suggerimenti, ma non riesco a farlo funzionare.parametri con chiusure opzionali in swift

Il mio codice:

func DoAlert(title: String 
    , message: String 
    , actions: String 
    , sender: AnyObject? 
    , Ctlr : UIViewController 
    , SegueString: String? 
    , YesClosure:()->() = {} 
    , NoClosure:()->() = {} 
    , StartClosure:()->() = {} 
    , EndClosure:()->() = {} 
    ) { 

if (actions.rangeOfString("Ok") != nil { 
     alert.addAction(UIAlertAction(title: "OK", style: .Default) { action -> Void in 
      EndClosure() 
      })} 
} // end function 

voglio aggiungere una chiusura per Ok, in cui è necessario il parametro 'sé'.

Qualcosa come di seguito:

// add to func doAlert: 
    , OkClosure: (AnyObject)->() = {} 


      // add to action Ok (before the EndClosure: 
      OkClosure(sender!) 

Ottenere errore sulla prima linea: ANYOBJECT non è sottotipo di()

Se lascio ANYOBJECT dalla prima linea, errore di ottenere: Impossibile convertire l'espressione di digitare 'AnyObject' per digitare '() =>()'

Tutte le altre prove mi danno errori simili "Tuple". Come codifico il passaggio dei parametri nelle chiusure opzionali nel mio codice?

+1

Un po 'più bello: 'SìClosure: (() ->())? = nil' e quindi usarlo in questo modo: 'YesClosure?()' (funziona solo se è impostato). Utilizza anche lowerCaseCamelCasing per parametri, variabili e istanze. – vrwim

+1

'DoAlert' * potrebbe * avere troppi argomenti. Non c'è modo di scrivere codice pulito quando si dispone di un metodo che richiede 10 argomenti, aggravato dal fatto che quattro di essi sono chiusi. – nhgrif

+0

nhgrif. Posso vedere il tuo punto di vista. DoAlert però è lì per creare codice pulito ovunque voglio simulare la "message box" VB. – ReneMusters

risposta

17

In primo luogo, da usare chiusure come argomento per una funzione, si dovrebbe dichiarare la loro in questo modo:

func myFunc(closure: (Int) -> Void) { 
    // Now I can call closure like so: 
    let myInt = 10 
    closure(myInt) 
} 

(Come sottolineato da @Airspeed Velocity, la parentesi intorno Int non sono strettamente necessario perché c'è solo un argomento Se si include loro è solo preferenza personale)

in secondo luogo, è possibile modificare la funzione precedente per includere una chiusura facoltativa, come segue:. (N ota la parentesi ? e intorno alla chiusura che indicano la chiusura è una, non è il tipo di ritorno opzionale)

func myFunc(closure: ((Int) -> Void)?) { 
    // Now when calling the closure you need to make sure it's not nil. 
    // For example: 
    closure?(10) 
} 

In terzo luogo, per aggiungere un valore di default pari a zero, che è quello che sembra si sta cercando a che fare con la = {} sulla fine di YesClosure:()->() = {}, si potrebbe fare:

func myFunc(closure: ((Int) -> Void)? = nil) { 
    // Still need to make sure it's not nil. 
    if let c = closure { 
     c(10) 
    } 
} 

Infine, proprio come una nota, è possibile impostare i nomi degli argomenti della chiusura, che può rendere più facile l'identificazione cosa tu' passare alla chiusura quando lo si chiama. Per esempio:

(Nota - qui parentesi sono tenuti intorno value: Int)

func myFunc(closure: ((value: Int) -> Void)) { 
    closure(value: 10) 
} 

Ancor più, infine, è possibile utilizzaretypealias. Secondo la documentazione:

A type alias declaration introduces a named alias of an existing type into your program.

Ecco un esempio di come usarlo con una chiusura:

typealias MyClosureType =() -> Void 

func myFunc(closure: MyClosureType) { 
    closure() 
} 

Speranza che aiuta!

+0

Bella risposta! Ma una cosa, quando dici "Quando usi le chiusure come argomenti di funzione devi assicurarti di includerle tra parentesi", non hai davvero bisogno di farlo (IMHO aggiunge solo clutter) a meno che tu non voglia fare qualcosa come mark l'intera chiusura opzionale –

+0

Questo è bello, non mi ero reso conto che avresti potuto farlo! Sono d'accordo, non avendo una parentesi in più rimuove la confusione.Modificherò la mia risposta di conseguenza – ABakerSmith

+0

Puoi anche lasciare le parentesi attorno ai singoli argomenti (cioè ' Int -> Void' invece di '(Int) -> Void') sebbene sia più una preferenza personale (lo preferisco) –

0

Penso di averlo trovato.Non posso usare i parametri nella chiusura quando chiamo func. Nel func stesso ho bisogno di definire i parametri usati (closure: (mittente: AnyObject) -> Void), assicurati che le variabili siano definite (o fornite come parametro separato) e le aggiunga alla chiamata di chiusura.

@IBAction func buttonPressed(sender: AnyObject) { 
    myFunc (sender, doClosure) 
} 

func myFunc(sender: AnyObject, closure: (sender: AnyObject) -> Void) { 
    // Now I can call closure like so: 
    closure (sender: sender) 
} 

func doClosure(sender: AnyObject) { 
    println("sender = \(sender)") 
}