web-dev-qa-db-fra.com

Comprendre la comparaison NSString

Les deux comparaisons suivantes sont vraies:

1)

@"foo" == @"foo";

2)

NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
myString1 == myString2;

Cependant, il y a certainement des moments où deux NSStrings ne peuvent pas être comparés à l'aide de l'opérateur d'égalité et [myString1 isEqualToString:myString2] est requis à la place. Quelqu'un peut-il nous éclairer à ce sujet?

82
Yarin

La raison pour laquelle == fonctionne est en raison de la comparaison pointeur. Lorsque vous définissez une constante NSString en utilisant @"", le compilateur unifie la référence. Lorsque les mêmes constantes sont définies à d'autres endroits dans votre code, elles pointeront toutes vers le même emplacement réel en mémoire.

Lorsque vous comparez des instances de NSString, vous devez utiliser le isEqualToString: méthode:

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];

Modifier:

NSString *myString3 = [[NSString alloc] initWithString:@"foo"]; 
// this is same with @"foo"

initWithString: ne crée plus de nouvelle référence, vous aurez besoin de initWithFormat,

NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
162
Jacob Relkin

L'opérateur d'égalité == compare uniquement les adresses de pointeur. Lorsque vous créez deux chaînes identiques à l'aide du littéral @"" _, le compilateur détectera leur égalité et ne stockera les données qu’une seule fois. Par conséquent, les deux pointeurs pointent vers le même emplacement. Cependant, les chaînes créées par d'autres moyens peuvent contenir des données identiques mais être stockées à des emplacements de mémoire différents. Par conséquent, vous devriez toujours utiliser isEqual: lors de la comparaison de chaînes.

Notez que isEqual: et isEqualToString: renvoie toujours la même valeur, mais isEqualToString: est plus rapide.

13
David M.

== compare les emplacements en mémoire. ptr == ptr2 _ s'ils pointent tous les deux vers le même emplacement mémoire. Cela arrive à travailler avec des constantes de chaîne parce que le compilateur utilise n chaîne réelle pour des constantes de chaîne identiques. Cela ne fonctionnera pas fonctionnera si vous avez des variables ayant le même contenu, car elles pointeront vers des emplacements de mémoire différents; utilisez isEqualToString dans un tel cas.

10
mipadi

Dans Cocoa, les chaînes sont comparées à l'aide de la chaîne NSString isEqualToString: méthode.

La comparaison de pointeur fonctionne dans votre cas car le compilateur est suffisamment souple pour fusionner les deux littéraux de chaîne afin de pointer vers un objet. Rien ne garantit que deux chaînes identiques partagent une instance NSString.

6
Nikolai Ruhe

Un exemple démontrant comment la comparaison d'adresses en tant que substitut pour la comparaison de chaînes va casser:

    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];
3
SK9

Découvrez cet exemple:

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

Ainsi, le compilateur utilisera probablement la méthode isEqualToString pour traiter isEquals for NSString et les pointeurs de déréférencement, bien que ce ne soit pas le cas. Et les pointeurs sont différents, comme vous le voyez.

0
Dmitry Zvorikin