2012-07-31 28 views
22

Antes que nada, disculpe esta simple pregunta. Pero necesito entender lo que está sucediendo.Objetivo C - Pase por valor y pase por referencia

Pensé que la salida debería ser upper case string. Pero resulta ser 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]; 
} 

¿Qué está pasando y cómo solucionarlo?

Respuesta

52

La llamada [string lowercaseString] crea un objeto nuevo NSString que se asigna a la variable local string. Esto no cambia el valor de stringVar fuera de la función changeString. El puntero se pasa por valor.

Una manera de hacer lo que quiera, es pasar un puntero a un puntero:

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

sólo para asegurarse, ARC se ocuparía de la manipulación, incluso en este caso de forma transparente la memoria, ¿verdad? –

+0

Querido Greg: Esto significa que el Objetivo C usa de forma predeterminada el mecanismo de pasar por valor ¿no? –

+0

@JoachimIsaksson: Sí, ARC maneja la administración de memoria correctamente (el compilador le avisará si no puede entender lo que está haciendo). –

0

cadena en -(void) changeString:(NSString*)string es variable local, método para devolver valor de forzado mira la referencia al [NSString lowerCaseString]method, puedes ver que devuelve una nueva cadena, con los caracteres en minúscula:

Devuelve la representación en minúscula del receptor.

- (NSString *)lowercaseString 

Lo que hace el código es simplemente sobrescribir la referencia a la cadena de entrada con la salida de la llamada lowercaseString, que no tiene ningún efecto. La mejor manera de resolver este problema es para que pueda devolver el valor a sí mismo, lo que hace que el método más fácil de entender:

-(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; 
} 

Es necesario comprender que NSString es inmutable por lo que no hay manera, aparte de la reasignación de la referencia , para cambiar el contenido de una cuerda. Sin embargo, podría usar NSMutableString, que puede modificarse en su lugar.

+0

Asignar NSString a un método 'Void' es un error y un método' Void' no devuelve un valor – Sumanth

+0

lo siento, mi mal, el valor de retorno de cource es 'NSString *' –

5

Si:

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

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

string es una variable local (un puntero a un NSString que es inmutable), estas a cambiar lo string puntos en el local de la función, pero cuando regrese a su valor serán desechados.

Lo que puede querer hacer es simplemente pasar la cadena como un parámetro y devolver la cadena de minúsculas de la función.

1

Me refiero al anterior problema dado y que le ayuda con la mistake.Find mis comentarios

- (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 
} 
Cuestiones relacionadas