2012-07-31 15 views
22

Prima di tutto, mi dispiace per questa semplice domanda. Ma ho bisogno di capire cosa sta succedendo.Obiettivo C - Passaggio per valore e passaggio per riferimento

Ho pensato che l'uscita dovrebbe essere upper case string. Ma risulta essere UPPER CASE STRING.

- (void)test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    [self changeString:stringVar]; 
    NSLog(@"value after changed : %@", stringVar); 
} 

- (void)changeString:(NSString*)string 
{ 
    string = [string lowercaseString]; 
} 

Che cosa sta succedendo e come risolverlo?

risposta

52

La chiamata [string lowercaseString] crea un oggetto nuovaNSString che si assegna alla variabile locale string. Ciò non modifica il valore di stringVar all'esterno della funzione changeString. Il puntatore stesso viene passato per valore.

Un modo per fare ciò che si vuole, è quello di passare un puntatore a un puntatore:

-(void) test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    stringVar =[self changeString:stringVar]; 
    NSLog(@"value after changed : %@", stringVar); 
} 
-(NSString *) changeString:(NSString*)string 
{ 
    return [string lowercaseString]; 
} 
+0

solo per assicurarsi che, ARC avrebbe gestito la movimentazione anche in questo caso in modo trasparente la memoria, giusto? –

+0

Caro Greg, Questo significa che l'Objective C utilizza per default il meccanismo del passaggio per valore, giusto? –

+0

@JoachimIsaksson: Sì, ARC gestisce correttamente la gestione della memoria (il compilatore ti avviserà se non riesce a capire cosa stai facendo). –

0

stringa -(void) changeString:(NSString*)string è variabile locale, metodo per restituire valore di comando guarda il riferimento allo [NSString lowerCaseString]method, puoi vedere che restituisce una nuova stringa, con i caratteri minuscoli:

Restituisce la rappresentazione in minuscolo del ricevitore.

- (NSString *)lowercaseString 

Che il codice fa è semplicemente sovrascrivere il riferimento alla stringa di input con l'uscita della chiamata lowercaseString, che non ha alcun effetto. Il modo migliore per risolvere questo problema è per voi di restituire il valore da soli, il che rende il metodo più facile da capire:

-(void) test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    stringVar = [self changeString:stringVar]; 
    NSLog(@"value after changed : %@", stringVar); 
} 

-(NSString *) changeString:(NSString*)string 
{ 
    string = [string lowercaseString]; 
    return string; 
} 

è necessario capire che NSString è immutabile quindi non c'è modo, diverso da quello riassegnando il riferimento , per cambiare il contenuto di una stringa. È possibile, tuttavia, utilizzare invece NSMutableString, che può essere modificato in posizione.

+0

L'assegnazione di NSString a un metodo 'Void' è un errore e un metodo' Void' non restituisce un valore – Sumanth

+0

scusate, il mio male, del valore di ritorno cource è 'NSString *' –

5

Se:

-(void) test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    [self changeString:&stringVar]; 
    NSLog(@"value after changed : %@", stringVar); 
} 

-(void) changeString:(NSString**)string 
{ 
    *string = [*string lowercaseString]; 
} 
0

string è una variabile locale (un puntatore a una NSString che è immutabile), si sta solo cambiando ciò che string punti nella funzione locale, ma quando si restituisce il suo valore verrà gettato via.

Quello che si potrebbe voler fare è semplicemente passare la stringa come parametro e restituire la stringa in minuscolo dalla funzione.

1

Mi riferisco al di sopra determinato problema e aiutandovi con la mistake.Find miei commenti

- (void)test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    //StringVar is a pointer to integer class.let us assume the address the stringVar be 0x50 and the value it has be 0x100 
    //So 0x100 has the string 

    [self changeString:stringVar]; 
    //above we are calling the method to lowercase and argument is stringVar 
    //As the method is called we pass 0x100 in the argument as this is the memory where the value is kept 

    NSLog(@"value after changed : %@", stringVar); 
    //Our StringVar still points to 0x100 where the value is in upperString 
} 

- (void)changeString:(NSString*)string 
{ 
    string = [string lowercaseString]; 
    // Now operation performed on string returns a new value on suppose location 0x200 
    //String parameter passed in argument is assigned the new value.But we never pass values as we pass only location under the hood 
    //New parameter passed now points to new memory location 0x200 

} 

--------------------------------------------------------------------------------- 
With the new solution 
-(void) test 
{ 
    NSString *stringVar = @"UPPER CASE STRING"; 
    //let 0x50 be stringVar memorylocation pointing to 0x100 with above value 
    [self changeString:&stringVar]; 
    //0x50 is passed in argument 
    NSLog(@"value after changed : %@", stringVar); 
    //On new location stored in address of stringVar it points to new string value 
} 

-(void) changeString:(NSString**)string 
{ 
    *string = [*string lowercaseString]; 
    //0x200 is new memory location received.*string gives the 0x100 location and hence the value 
    //LHS is assigned to new location .On LHS you find *string which will be assigned 0x200 
    //As string with location 0x50 is value 0x200 which will make it to point new  location where lowercase string exist 
} 
Problemi correlati