2012-11-13 12 views
5

Se ho un metodo Objective-C che accetta un parametro oggetto e detto metodo utilizza un blocco per eseguire internamente il proprio lavoro, esiste un modo per modificare tale oggetto all'interno del blocco?Come posso modificare i parametri di un metodo ObjC all'interno di un blocco?

È a mia conoscenza che blocchi le variabili di acquisizione dall'ambito genitore facendo riferimento a esse all'interno del blocco e che vengano copiate per impostazione predefinita. E se voglio essere in grado di modificare piuttosto che lavorare con una copia di un oggetto circostante, posso prefisso la sua dichiarazione con __block, ma non riesco a farlo con i parametri del metodo poiché non l'ho dichiarato io stesso, giusto?

Ad esempio:

- (void)doWorkWithString:(NSString *)someString 
{ 
    [NSFoo doAwesomeClassMethodWithBlock:^{ 
     // How can I modify someString here directly? 
     // By just changing someString, I'm changing the captured copy 
    }]; 
} 
+0

Sono troppo pigro per cercare i documenti, ma non credo che le variabili acquisite in un blocco vengano copiate; sarebbe molto sorprendente dal momento che gli oggetti potrebbero non implementare la copia. Se __block non è specificato, gli oggetti verranno comunque mantenuti dal blocco. All'interno del blocco, i puntatori di oggetti non sono diversi da qualsiasi altra parte, quindi per rispondere alla tua domanda puoi modificarli come preferisci. Quello che non puoi fare è scrivere su una variabile che è stata catturata * IF * __block non è stato fornito. Le variabili contrassegnate con __block non vengono mantenute dal blocco, quindi fai attenzione. Speriamo che abbia un senso. –

+0

@darren: le variabili di blocco non -__ in un blocco * sono * copiate. Ma il valore di una variabile non è mai un oggetto. È possibile avere solo un * puntatore dell'oggetto *. Quindi, sì, quando un blocco acquisisce un puntatore a oggetti, copia il puntatore. Questo non ha assolutamente nulla a che fare con la copia di oggetti. – newacct

+0

Intendevo il parametro "puntatore dell'oggetto" quando ho detto "parametro oggetto". per esempio. Passando un'istanza NSString *. –

risposta

1

Quello che dici su di cattura è corretta; quello che probabilmente vuoi fare è fornire gli argomenti che dovrebbero essere il soggetto del blocco come argomenti ad esso - proprio come se tu stessi chiamando una funzione C. Quindi ad es.

void (^ someBlock)(NSString *) = 
    ^(NSString *someString) 
    { 
     NSLog(@"length is %d", [someString length]); 
    }; 

... 

someBlock(@"String 1"); 
someBlock(@"A second string"); 
1

Mi sono reso conto che il mio commento sopra era incredibilmente confuso. Speriamo che la seguente schiarisce quello che stavo cercando di dire:

- (void)yourMethod:(Foo *)parameterFoo 
{ 
    __block Foo *blockVariable = [Foo someFoo]; 
    Foo *capturedVariable = [Foo anotherFoo]; 

    void(^doWorkBlock)(Foo *bp) = ^(Foo *bp){ 
     // If your block accesses a scoped variable that is not marked with __block, it will 
     // retain it, so here capturedVariable and bp would be retained by the block 
     capturedVariable.aProperty = 5.0; 
     bp.aProperty = 10.0; 

     // As you can see, you can modify the objects all you like.   
     // What you cannot do is assign something to capturedVariable or bp because they 
     // were not marked as __block 
     // WONT WORK 
     capturedVariable = [Foo new]; 

     // However, you can write to blockVariable because it is marked as __block 
     // WORKS 
     blockVariable = [Foo new]; 
     // Remember, though that the block will not retain this variable itself because 
     // of the __block 
    }; 

    // Note, it's weird for the block to take a parameter since it could just access the 
    // variable directly. This just serves to show how a block would handle a parameter. 
    doWorkBlock(parameterFoo); 
} 
2

"che accetta un parametro oggetto"

Prima di tutto, si è quasi certamente confuso dal fatto che non si può avere un parametro o variabile di tipo di oggetto. Puoi solo avere puntatori agli oggetti. Quindi sì, le variabili non __block catturate da un blocco vengono copiate dal blocco. Ma qui le variabili sono primitive o puntatori di oggetti, non "oggetti".

Se è necessario solo modificare l'oggetto puntato da un puntatore a un oggetto e ciò non comporta la modifica del puntatore per puntare a un altro oggetto, non si modifica la variabile. E poiché non stai cambiando la variabile, tutto questo "copiare la variabile" e le cose __block sono completamente irrilevanti.

Problemi correlati