Mi è stato chiesto quale sia il vantaggio, o svantaggio, nell’uso delle funzioni anonime o inline (o onfly), utilizzate moltissimo in Javascript e, oramai con la 5.3, anche in PHP.
Una funzione inline, o anonima perché non ha – appunto – un nome, è un modo veloce per scrivere alcune procedure, indentando ad albero sequenze di callback ad esempio. Quasi tutti i linguaggi supportano la scrittura di funzioni di questo, ognuno al limite con le sue peculiarità e restrizioni. Possono anche avere nomi diversi e sintassi particolari, come i cosiddetti blocks in Objective-C.
Articoli con Tag ‘callback’
Funzioni anonime
iPhone: creare un metodo per rispondere agli eventi cross class
Normalmente un evento, che altro non è che un messaggio, viene risolto (impostato ed implementato) nella stessa classe o contesto, della funzione o procedura “chiamante”. Ad esempio se aggiungiamo un bottone UIButton via codice (programmatically), possiamo trovarci all’interno di una nostra classe UIView o in un UIViewController. In entrambi i casi l’operazione di allocazione e inizializzazione del bottone sarà seguita dall’impostazione del target che dovrà ricevere un messaggio quando si “cliccherà” sul bottone, sul tipo:
1 2 3 4 5 6 7 8 9 | UIButton *bottone = [UIButton buttonWithType:UIButtonTypeRoundedRect]; bottone.frame = CGRectMake(10, 180, 300, 30); [bottone setTitle:@"Press me" forState:UIControlStateNormal]; // decide chi deve ricevere il messaggio UIControlEventTouchUpInside [bottone addTarget:self action:@selector(onButtonClicked) forControlEvents:UIControlEventTouchUpInside]; // ... - (void) onButtonClicked { // ... } |
La riga 5 del codice mostrato sopra decide chi (l’oggetto) e cosa (il metodo) “chiamare” quando il nostro bottone è stato premuto. Nell’esempio sopra illustrato si nota anche che l’impostazione del messaggio di pressione viene inviato al metodo onButtonClick implementato più sotto, quindi facente parte dello stesso contesto (o classe). La prima considerazione ovvia che possiamo fare, dunque, è che alterando i parametri self e action potremmo inviare il nostro messaggio ad un qualsiasi altro oggetto, posto quindi al difuori del contesto in uso. Ecco un esempio pratico: una classe UIApplicationDelegate crea un UIViewController:
1 2 3 4 5 | // // myAppDelegate.m // splashScreenController = [SplashScreenController alloc]; [window addSubview:splashScreenController.view]; |
Lo SplashScreenController espone un metodo che permette di animare la UIView associata al UIViewController stesso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // // SplashScreenController.m // - (void) animateBackgroundDown { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.75]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(onAnimationFinished)]; self.view.frame = (CGRect){0,480,320,480}; [UIView commitAnimations]; } // ... - (void) onAnimationFinished { NSLog(@"Animazione terminata"); } |
Il codice sopra mostra un metodo definito all’interno della classe SplashScreenController di tipo UIViewController. Esso non fa altro che animare la UIView animandola verso il basso e, quando l’animazione è terminata, chiamare il metodo (invia un messaggio a se stesso – da qui self) onAnimationFinished definito più sotto, facente parte sempre della classe SplashScreenController. Ne segue che nella nostra myAppDelegate, quando invocheremo il metodo animateBackgroundDown, non saremo informati della fine dell’animazione:
1 2 3 4 | // // myAppDelegate.m // [splashScreenController animateBackgroundDown]; |
Quello che potremmo desiderare, invece, è realizzare una nuova versione di animateBackgroundDown tale da dirgli a chi inviare il messaggio di fine animazione e quale metodo chiamare. In pratica vogliamo fare in modo di poter scrivere nella nostra classe myAppDelegate:
1 2 3 4 5 6 7 8 | // // myAppDelegate.m // [splashScreenController animateBackgroundDown:self selector:@selector(onAnimationFinished)]; // ... - (void) onAnimationFinished { NSLog(@"Animazione terminata"); } |
Questa volta il metodo onAnimationFinished non si trova nel UIViewController, bensì in myAppDelegate. Per fare questo è sufficiente modificare il metodo animateBackgroundDown nel UIViewController nel modo seguente:
1 2 3 4 5 6 7 8 9 10 11 12 | // // SplashScreenController.m // - (void) animateBackgroundDown:(id)target selector:(SEL)selector { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.75]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:target]; [UIView setAnimationDidStopSelector:selector]; self.view.frame = (CGRect){0,480,320,480}; [UIView commitAnimations]; } |
Adesso abbiamo un metodo che accetta il “contesto” (target) e il metodo da chiamare (selector). Adesso, quando l’animazione termina, il messaggio AnimationDidStop sarà inviato a myAppDelegate a qualsiasi altro “oggetto” / classe in grado di riceverlo.
WordPress: ordinare una serie di post per un campo qualsiasi
La tecnica che illustro qui è utile in molte situazioni dove, ad esempio, abbiamo un array di array o un array di oggetti. In WordPress può capitare di dover manipolare un elenco di post, nel formato standard di array di stdClass Object, senza aver accesso alla select originale (sul database) che ha generato l’elenco (array) stesso:






Ultimi Commenti
Andrea: Un altra spiegazione dettagliata la potete trovare qui!! http://www.cianiandrea.it/arch ives/413
Daniela: Ciao! Provo a chiederti un aiuto per risolvere il mio problema. Sto migrando il mio blog da tumblr a...
Giovambattista Fazioli: @ale: Come indicato @Kevin vedi sul repo di GitHub: https://github.com/gfazioli/Ch roma-Key
Giovambattista Fazioli: @Kevin: See https://github.com/gfazioli/Ch roma-Key
Kevin: Very nice example – would like to see the .fla too!