Diferencia entre los literales NSString

¿Cuál es la diferencia entre estas dos líneas?

NSString * string = @"My String"; NSString * string = [[[NSString alloc] initWithString:@"MyString"] autorelease] 

@ “Mi cadena” es una cadena literal comstackda en el binario. Cuando está cargado, tiene un lugar en la memoria. La primera línea declara una variable que apunta a ese punto en la memoria.

De la guía de progtwigción de cuerdas:

La forma más sencilla de crear un objeto de cadena en el código fuente es usar la construcción Objective-C @ “…”:

 NSString *temp = @"/tmp/scratch"; 

Tenga en cuenta que, al crear una constante de cadena de esta manera, debe evitar usar cualquier cosa que no sean caracteres ASCII de 7 bits. Tal objeto se crea en tiempo de comstackción y existe a lo largo de la ejecución de su progtwig. El comstackdor hace que esas constantes de objeto sean únicas por cada módulo y nunca se desasignan, aunque puede retenerlas y liberarlas como lo hace con cualquier otro objeto.

La segunda línea asigna una cadena tomando esa cadena literal. Tenga en cuenta que las cadenas literales @ “My String” son las mismas. Para probar esto:

 NSString *str = @"My String"; NSLog(@"%@ (%p)", str, str); NSString *str2 = [[NSString alloc] initWithString:@"My String"]; NSLog(@"%@ (%p)", str2, str2); NSString *copy = [str2 stringByAppendingString:@"2"]; NSLog(@"%@ (%p)", copy, copy); 

Envía la misma dirección de memoria:

 2011-11-07 07:11:26.172 Craplet[5433:707] My String (0x100002268) 2011-11-07 07:11:26.174 Craplet[5433:707] My String (0x100002268) 2011-11-07 07:11:26.174 Craplet[5433:707] My String2 (0x1003002a0) 

Lo que está diciendo es que las dos primeras cadenas no son la misma dirección de memoria, pero si no cambias el código, es la misma dirección de memoria cada vez que la ejecutas. Es el mismo desplazamiento binario en la memoria. Pero, no solo es la copia diferente sino que es diferente cada vez que la ejecuta, ya que está asignada en el montón.

La liberación automática no tiene ningún efecto de acuerdo con el doc ref anterior. Puede liberarlos, pero nunca se desasignan. Por lo tanto, son iguales no porque ambos sean cadenas de autorretrato, sino que son ambas constantes y el lanzamiento se ignora.

Uno es una cadena literal, que persiste durante la vida de la aplicación de ejecución. El otro puede ser un objeto dynamic que solo persiste hasta que se libera automáticamente. (También puede ser una cadena literal, si el sistema decide optimizarla de esa manera; no hay garantías de que no lo haga).

bryanmac es 100% correcto en su respuesta. Acabo de agregar un ejemplo explícito usando GHUnit .

Creación de NSString – literal contra no literal.

Muestra cadenas creadas de varias maneras si son literales o no literales.

 - (void) test_stringCreation { NSString *literalString = @"literalString"; NSString *referenced = literalString; NSString *copy = [literalString copy]; NSString *initWithString = [[NSString alloc] initWithString:literalString]; NSString *initWithFormat = [[NSString alloc] initWithFormat:@"%@", literalString]; // Testing that the memory addresses of referenced objects are the same. GHAssertEquals(literalString, @"literalString", @"literal"); GHAssertEquals(referenced, @"literalString", @"literal"); GHAssertEquals(copy, @"literalString", @"literal"); GHAssertEquals(initWithString, @"literalString", @"literal"); GHAssertNotEquals(initWithFormat, @"literalString", @"nonliteral - referenced objects' memory addresses are \ different."); // Testing that the objects referenced are equal, ie isEqual: . GHAssertEqualObjects(literalString, @"literalString", nil); GHAssertEqualObjects(referenced, @"literalString", nil); GHAssertEqualObjects(copy, @"literalString", nil); GHAssertEqualObjects(initWithString, @"literalString", nil); GHAssertEqualObjects(initWithFormat, @"literalString", nil); // Testing that the strings referenced are the same, ie isEqualToString: . GHAssertEqualStrings(literalString, @"literalString", nil); GHAssertEqualStrings(referenced, @"literalString", nil); GHAssertEqualStrings(copy, @"literalString", nil); GHAssertEqualStrings(initWithString, @"literalString", nil); GHAssertEqualStrings(initWithFormat, @"literalString", nil); } 

No hay diferencia entre ellos. Una cadena iniciada como se muestra en el primer ejemplo es una cadena autorrellenada.

Solo recuerda esto básico:

 NSString *string = ... 

¡Este es un puntero a un objeto, “no un objeto”!

Por lo tanto, la instrucción: NSString *string = @"Hello"; asigna la dirección del objeto @"Hello" a la cadena del puntero.

@"Hello" se interpreta como una cadena constante por el comstackdor y el propio comstackdor asigna la memoria para ello.

Del mismo modo, la statement

 NSObject *myObject = somethingElse; 

asigna la dirección de somethingElse al puntero myObject , y ese somethingElse ya debe asignarse e inicializarse.

Por lo tanto, la instrucción: NSObject *myObject = [[NSObject alloc] init]; asigna e inicializa un objeto NSObject y asigna su dirección a myObject .