2011-01-06 10 views
11

Sto cercando di capire come utilizzare i blocchi su iOS. Ho letto i documenti di Apple ma, come al solito, sono vaghi e incompleti e non vengono menzionate molte informazioni essenziali. Ho anche cercato su Google senza successo. Questo è quello che sto cercando di fare come esercizio per capirlo.Cercando di capire i blocchi su iOS

Ho creato un blocco per leggere una stringa e confrontare la stringa con la lettura precedente. Se le stringhe non sono le stesse, restituire SÌ, se sono uguali, restituire NO.

Ecco come ho fatto:

ho dichiarato questo sul .h

BOOL (^differentStrings)(void); 

ho dichiarato questo su .m, all'interno viewDidLoad in un viewController

__block NSString * previousString; 
__block NSString * currentString; 
differentStrings = ^(void){ 

    currentString = [self getString]; 
    NSLog(@"%@", currentString); // not printing anything on console 

    if (![currentString isEqualToString:previousString]) { 
     previousString = currentString; 
     return YES; 
    } else { 
     return NO; 
    } 
}; 

Questo è come mi uso: Ho una discussione che fa questo:

if (differentStrings) 
    NSLog (@"strings are different); 

Questi sono i problemi che ho:

  1. il blocco ritornano sempre SI (stringhe sono diverse)
  2. io non sono confortevoli dichiarando questo videDidLoad all'interno. Come dovrei dichiararlo, quindi posso usarlo globalmente come metodo? Dovrei metterlo come vorrei con un metodo?
  3. Sto chiamando un metodo "getString" all'interno del blocco. Va bene?
  4. Trovo strano dichiarare le variabili di blocco su .m. Come vedo, dovrei dichiarare le variabili di blocco su .h e poi usarle semplicemente su .m. Ho provato a farlo, ma ho ricevuto un errore.
  5. Ho impostato un punto di debug sulla prima riga del blocco ma non si ferma lì;
  6. La riga NSlog all'interno del blocco non stampa nulla. Il blocco non viene chiamato?

Potete aiutarmi con questo?

risposta

15

Stai fraintendendo come funzionano i blocchi. (Ok, quindi è abbastanza ovvio). Allo stesso modo che previousString è una variabile che punta a una NSString, differentStrings è una variabile che punta a un blocco . Non è il risultato dell'esecuzione del blocco, ma piuttosto del blocco stesso. Cioè, dopo aver effettuato l'operazione:

__block NSString * previousString; 
__block NSString * currentString; 
differentStrings = ^(void){ 

    currentString = [self getString]; 
    NSLog(@"%@", currentString); // not printing anything on console 

    if (![currentString isEqualToString:previousString]) { 
     previousString = currentString; 
     return YES; 
    } else { 
     return NO; 
    } 
}; 

differentStrings è una variabile che punta al blocco .Così, quando si esegue questa operazione:

if (differentStrings) 

... si sta semplicemente controllando se differentStrings contiene qualcosa diverso da 0 o NULL. Poiché contiene un blocco, non è vuoto, quindi viene valutato true.

Ricorda: differentStrings è una variabile di blocco, non una variabile BOOL. Contiene un blocco (una funzione, se vuoi), che quando chiama restituirà un bool. Pertanto, per poter eseguire effettivamente il blocco, è necessario chiamarlo. Come questo:

differentStrings(); 

o, nel tuo caso:

if (differentStrings()) { 
    NSLog (@"strings are different"); 
} 

Edit: Come sottolineato nei commenti, in quanto differentStrings è una variabile di istanza, è necessario copy esso, proprio come te Chiamare retain su qualsiasi altro oggetto assegnato a una variabile di istanza. (Per motivi tecnici non entrerò in questo momento, dovresti sempre usare copy con blocchi invece di retain.) Allo stesso modo, dovrai chiamare lo release su di esso ad un certo punto dopo, forse nel tuo metodo dealloc.

+1

Penso che avresti anche bisogno di "copiare" il blocco quando si assegna ad Ivar. Altrimenti, il blocco esce dallo scope quando si esce 'viewDidLoad'. Inoltre, mentre 'previousString' deve essere una variabile' __block', 'currentString' può essere una variabile locale block. –

+1

Assolutamente giusto. Ho aggiornato la mia risposta. –

+0

grazie per la risposta. Ho aggiunto la parentesi quando ho chiamato il blocco e ho anche fatto un Block_copy (differentStrings) dopo averlo creato su viewDidLoad ma si blocca quando chiamo il blocco usando differentStrings() ...Ho provato a chiamare il blocco dallo stesso scope e funziona, ma quando lo chiamo da un ambito diverso, si blocca, anche con Block_copy. – SpaceDog

3

non ho potuto ottenere la mia testa intorno blocchi finché non ho visto Block e Mulithreading da Stanfords Developing Apps for iOS

+0

grazie, quel video ha aiutato la comprensione più profondo, ma anche dopo aver visto che ho ancora le stesse domande, non sono anche affrontate da questa classe. – SpaceDog

4

non credo che si sta effettivamente eseguendo il blocco. Penso che il tuo codice dovrebbe essere

if (differentStrings()) 
{ 
    NSLog (@"strings are different); 
} 

Trattare un blocco come una funzione. Penso che stavi solo controllando per vedere se il blocco era stato definito, non per eseguirlo.

Inoltre, se non è necessario accedere a una NSString al di fuori del blocco, è possibile eliminare il qualificatore __block e spostare la dichiarazione currentString all'interno del blocco.

Se hai bisogno di un'altra risorsa su blocchi, li copro nella sessione autunnale del mio corso avanzato di sviluppo iOS on iTunes U. Descrivo la sintassi dei blocchi nella sessione Understanding Cocoa e il loro uso in Grand Central Dispatch nella sessione di multithreading. Le note del corso hanno anche collegamenti ad alcune applicazioni di esempio che usano i blocchi in modi diversi.

Inoltre, non posso raccomandare abbastanza che tu guardi le sessioni video WWDC 2010 206 - Presentazione di Blocchi e Grand Central Dispatch su iPhone e 211 - Semplificazione dello sviluppo di app per iPhone con Grand Central Dispatch.

+0

'previousString' deve essere una variabile' __block' perché il suo valore è referenziato tra le successive chiamate del blocco. Inoltre, il blocco deve essere copiato quando si assegna a Ivar o se ne andrà fuori campo. –

+1

@Daniel - Buon punto, ho letto male come stava usando quella stringa. –

+0

Grazie Brad, lo controllerò. – SpaceDog

Problemi correlati