La razón por la que ==
funciona es debido a la comparación de punteros. Cuando define un NSString
uso constante @""
, el compilador uniquifica la referencia. Cuando se definen las mismas constantes en otros lugares de su código, todas apuntarán a la misma ubicación real en la memoria.
Al comparar NSString
instancias, debe utilizar el isEqualToString:
método:
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
NSLog(@"%d", (myString2 == myString3))
NSLog(@"%d", (myString1 == myString2));
NSLog(@"%d", [myString1 isEqualToString:myString2]);
NSLog(@"%d", [myString1 isEqualToString:myString3]);
[myString3 release];
Editar:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
ya no crea una nueva referencia, necesitará initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
myString3
un puntero a la constante"foo"
como una optimización, por lo que, en general, estas tres variables apuntarán a la misma ubicación de memoria. Esto es cierto tanto para gcc como para clang (con opciones predeterminadas). Intente compilar esto: gist.github.com/578568isEqual:
de hecho, hace una comparación de cadena completa y devuelve el mismo resultadoisEqualToString
porque la Referencia de protocolo NSObject y la Referencia de clase NSString especifican explícitamente (respectivamente): "Si dos objetos son iguales (por-isEqual:
), deben tener el mismo valor hash "Y" Si dos objetos de cadena son iguales (según lo determinado por el método isEqualToString:), deben tener el mismo valor hash ".El operador de igualdad
==
solo compara direcciones de puntero. Cuando crea dos cadenas idénticas usando la@""
sintaxis literal , el compilador detectará que son iguales y solo almacenará los datos una vez. Por lo tanto, los dos punteros apuntan a la misma ubicación. Sin embargo, las cadenas creadas por otros medios pueden contener datos idénticos, pero almacenarse en diferentes ubicaciones de memoria. Por lo tanto, siempre debe usarloisEqual:
al comparar cadenas.Tenga en cuenta que
isEqual:
yisEqualToString:
siempre devuelve el mismo valor, peroisEqualToString:
es más rápido.fuente
isEqualToString
: causará una excepción si el parámetro que se le pasa esnil
. Entonces, si existe la posibilidad de que esté comparando con una cadena nula, primero debe hacer una verificación nula o usarisEqual:
==
compara ubicaciones en la memoria.ptr == ptr2
si ambos apuntan a la misma ubicación de memoria. Esto sucede que funciona con constantes de cadena porque el compilador usa una cadena real para constantes de cadena idénticas. No funcionará si tiene variables con el mismo contenido, porque apuntarán a diferentes ubicaciones de memoria; utilizarisEqualToString
en tal caso.fuente
En Cocoa, las cadenas se comparan utilizando el
isEqualToString:
método de NSString .La comparación de punteros funciona en su caso porque el compilador es lo suficientemente suave como para fusionar los dos literales de cadena para apuntar a un objeto. No hay garantía de que dos cadenas idénticas compartan una
NSString
instancia.fuente
NSString
instancias distintas con contenido idéntico:[NSMutableString string] != [NSMutableString string]
==
funcionalidad. Sin embargo, si elimina una NSString, asigna un valor y luego elimina otra NSString como estaNSString stringWithFormat:
, de hecho obtendrá dos cadenas diferentes que==
fallarán. Dijiste que no hay garantía de que dos instancias de NSString (no NSMutableString) compartan una instancia de NSString, y simplemente te pregunté si tenías alguna prueba de esa afirmación para poder compartirla.Un ejemplo que demuestra cómo se romperá la comparación de direcciones como sustituto de la comparación de cadenas:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *s1 = @"foo"; NSString *s2 = @"foo"; NSString *s3 = [[[NSString alloc] initWithString:@"foo"] autorelease]; NSMutableString *s4 = [NSMutableString stringWithString:@"foobar"]; [s4 replaceOccurrencesOfString:@"bar" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [s4 length])]; NSLog(@"s1 = %p\n", s1); NSLog(@"s2 = %p\n", s2); NSLog(@"s3 = %p\n", s3); NSLog(@"s4 = %p\n", s4); // distinct from s1 NSLog(@"%i", [s1 isEqualToString:s4]); // 1 [pool release];
fuente
Mira este ejemplo:
NSString *myString1 = @"foo"; NSMutableString *myString2 = [[NSMutableString stringWithString:@"fo"] stringByAppendingString: @"o"]; NSLog(@"isEquality: %@", ([myString1 isEqual:myString2]?@"+":@"-")); //YES NSLog(@"isEqualToStringity: %@", ([myString1 isEqualToString:myString2]?@"+":@"-")); //YES NSLog(@"==ity: %@", ((myString1 == myString2)?@"+":@"-")); // NO
Por lo tanto, es probable que el compilador use el método isEqualToString para procesar isEquals para los punteros de NSString y desreferenciar, aunque no tenía que hacerlo. Y los indicadores son diferentes, como ve.
fuente
NSString *str1=[NSString stringWithFormat:@"hello1"]; NSString *str2=[NSString stringWithFormat:@"hello1"]; NSString *str3 = [[NSString alloc] initWithString:@"hello1"]; // == compares the pointer but in our example we are taking same string value to different object using @ so it will point to same address so output will be TRUE condition if (str1==str2) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // == compares the pointer but in our example we are taking same string value to different object but we have allocated different string so both object will pount to different address so output will be FALSE condition if (str1==str3) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // compare:= compares the values of objects so output will be TRUE condition if ([str1 compare:str3]== NSOrderedSame) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // isEqual compares the values of objects so output will be TRUE condition if ([str1 isEqual:str2]) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // isEqual compares the values of objects so output will be TRUE condition if ([str1 isEqual:str3]) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // isEqualToString compares the values of objects so output will be TRUE condition if ([str1 isEqualToString:str2]) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // isEqualToString compares the values of objects so output will be TRUE condition if ([str1 isEqualToString:str3]) { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); } // == compares the pointers since we have initialized the same value to first object so the pointer be be same for same value so output will be TRUE condition if (str1==@"hello1") { NSLog(@"Both String are equal"); } else{ NSLog(@"Both String not are equal"); }
fuente