2014-06-13 22 views
11

Diciamo che ho un UIView personalizzato, chiamiamolo MyCustomView. All'interno di questa vista è presente una proprietà UITextField. Supponiamo che il mio obiettivo sia di creare un'istanza di MyCustomView e aggiungerla a qualche controller di visualizzazione da qualche parte, e voglio che quel controller di visualizzazione sia in grado di gestire le azioni intraprese su quel campo di testo. Per esempio, se ho colpito "ritorno" sulla tastiera all'interno del campo di testo, mi consiglia di fare qualche azione - lasciatemi fare un esempio di quello che sto immaginando con qualche Objective-C codice pseudo:iOS Swift Pass Chiusura come proprietà?

MyCustomView *myView = [[MyCustomView alloc] initWithFrame:CGRectMake(10,10,100,100)]; 
myView.textField.actionBlock = { /* do stuff here! */ } 
[self.view addSubview:myView]; 

E poi all'interno della classe MyCustomView vorrei fare qualcosa di simile:

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
    self.actionBlock(); 
    return NO; 
} 

mi piacerebbe il CustomView di essere l'UITextFieldDelegate in modo che ogni volta che faccio questo non dovrà aggiungere tutti i metodi delegato alla guarda i controller a cui sto aggiungendo, ma piuttosto una singola implementazione che fa semplicemente qualunque sia Ci passo sopra ... Come si fa a fare tutto questo in fretta?

risposta

35

Certo, puoi farlo. Swift ha funzioni di prima classe, quindi puoi fare cose come passare direttamente le funzioni come variabili. Tenete a mente, le funzioni stesse sono di fatto chiuse dietro le quinte. Ecco un esempio di base:

class MyClass { 
    var theClosure: (() ->())? 

    init() { 
     self.theClosure = aMethod 
    } 

    func aMethod() ->() { 
     println("I'm here!!!") 
    } 
} 


let instance = MyClass() 
if let theClosure = instance.theClosure { 
    theClosure() 
} 

instance.theClosure = { 
    println("Woo!") 
} 
instance.theClosure!() 

Ed ecco lo stesso esempio utilizzando le chiusure che possono assumere un parametro String.

class MyClass { 
    var theClosure: ((someString: String) ->())? 

    init() { 
     self.theClosure = aMethod 
    } 

    func aMethod(aString: String) ->() { 
     println(aString) 
    } 
} 

let instance = MyClass() 
if let theClosure = instance.theClosure { 
    theClosure(someString: "I'm the first cool string") 
} 

instance.theClosure = {(theVerySameString: String) ->() in 
    println(theVerySameString) 
    someThingReturningBool() 
} 
instance.theClosure!(someString: "I'm a cool string!") 
+0

Eccellente, grazie per le informazioni! Sto ancora afferrando gli optionals scartare e così, quindi mi chiedo cosa succede se voglio che la chiusura sia opzionale? Usando questo codice, se non viene fornita alcuna chiusura, si blocca. – Mike

+0

@Mike yeah mi dispiace per quello. Ho incluso lo scartare nella mia modifica. –

+0

Inoltre, un'altra stranezza semi-correlata. Diciamo che voglio chiamare una funzione all'interno della chiusura che fa qualcosa e restituisce un Bool, ma non mi interessa il risultato ... Sembra che devo fare qualcosa di simile a questo {var unusedResult = self.doSomethingThatAlsoReturnsBool()} altrimenti ottengo l'errore "Impossibile convertire l'espressione di tipo"() "in" Bool "". In qualsiasi modo posso evitare di creare e assegnare l'unusedResult? – Mike