Die beiden folgenden Vergleiche werden als wahr bewertet:
1)
@"foo" == @"foo";
2)
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
myString1 == myString2;
Es gibt jedoch definitiv Zeiten, in denen zwei NSString
s nicht mit dem Gleichheitsoperator verglichen werden können, und [myString1 isEqualToString:myString2]
ist stattdessen erforderlich. Kann jemand etwas Licht ins Dunkel bringen?
Der Grund, warum ==
Funktioniert, ist der Zeigervergleich. Wenn Sie eine Konstante NSString
mit @""
Definieren, macht der Compiler die Referenz eindeutig. Wenn dieselben Konstanten an anderen Stellen im Code definiert sind, verweisen sie alle auf dieselbe tatsächliche Position im Speicher.
Wenn Sie NSString
Instanzen vergleichen, sollten Sie die Methode isEqualToString:
Verwenden:
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
NSLog(@"%d", (myString2 == myString3)) //0
NSLog(@"%d", (myString1 == myString2)); //1
NSLog(@"%d", [myString1 isEqualToString:myString2]); //1
NSLog(@"%d", [myString1 isEqualToString:myString3]); //1
[myString3 release];
Bearbeiten:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
Erstellt keine neue Referenz mehr, Sie benötigen initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
Der Gleichheitsoperator ==
Vergleicht nur Zeigeradressen. Wenn Sie zwei identische Zeichenfolgen mit der Literal-Syntax @""
Erstellen, erkennt der Compiler, dass sie gleich sind, und speichert die Daten nur einmal. Daher zeigen die beiden Zeiger auf dieselbe Position. Mit anderen Mitteln erstellte Zeichenfolgen können jedoch identische Daten enthalten, die jedoch an verschiedenen Speicherorten gespeichert sind. Daher sollten Sie immerisEqual:
Zum Vergleichen von Zeichenfolgen verwenden.
Beachten Sie, dass isEqual:
Und isEqualToString:
Immer den gleichen Wert zurückgeben, aber isEqualToString:
Ist schneller.
==
vergleicht Positionen im Speicher. ptr == ptr2
, wenn beide auf denselben Speicherort zeigen. Dies geschieht, um mit Zeichenfolgenkonstanten zu arbeiten, da der Compiler eins tatsächliche Zeichenfolge für identische Zeichenfolgenkonstanten verwendet. Es funktioniert nicht, wenn Sie Variablen mit demselben Inhalt haben, da diese auf unterschiedliche Speicherorte verweisen. Verwenden Sie in diesem Fall isEqualToString
.
In Cocoa werden Strings mit NSStrings isEqualToString:
Methode.
Der Zeigervergleich funktioniert in Ihrem Fall, da der Compiler so intelligent ist, dass die beiden Zeichenfolgenliterale zusammengeführt werden, um auf ein Objekt zu verweisen. Es gibt keine Garantie dafür, dass zwei identische Zeichenfolgen eine NSString
-Instanz gemeinsam haben.
Ein Beispiel, das zeigt, wie der Adressvergleich als Ersatz für den Zeichenfolgenvergleich funktioniert:
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];
Schauen Sie sich dieses Beispiel an:
NSString *myString1 = @"foo";
NSMutableString *myString2 = [[NSMutableString stringWithString:@"fo"] stringByAppendingString: @"o"];
NSLog(@"isEquality: %@", ([myString1 isEqual:myString2][email protected]"+":@"-")); //YES
NSLog(@"isEqualToStringity: %@", ([myString1 isEqualToString:myString2][email protected]"+":@"-")); //YES
NSLog(@"==ity: %@", ((myString1 == myString2)[email protected]"+":@"-")); // NO
Daher verwendet der Compiler wahrscheinlich die Methode isEqualToString, um isEquals für NSString- und Dereferenzierungszeiger zu verarbeiten, obwohl dies nicht erforderlich war. Und die Zeiger sind anders, wie Sie sehen.