La raison pour laquelle cela ==
fonctionne est à cause de la comparaison de pointeurs. Lorsque vous définissez une constante à l' NSString
aide @""
, le compilateur unifie la référence. Lorsque les mêmes constantes sont définies à d'autres endroits de votre code, elles pointeront toutes vers le même emplacement réel en mémoire.
Lorsque vous comparez des NSString
instances, vous devez utiliser la isEqualToString:
méthode:
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];
Éditer:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
ne crée plus de nouvelle référence, il vous en faudra initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
myString3
un pointeur vers la constante"foo"
comme optimisation, donc généralement, ces trois variables pointeront vers le même emplacement mémoire. Ceci est vrai pour gcc et clang (avec les options par défaut). Essayez de compiler ceci: gist.github.com/578568isEqual:
fait en fait une comparaison de chaîne complète et retourne le même résultat queisEqualToString
parce que la référence de protocole NSObject et la référence de classe NSString spécifient explicitement (respectivement): "Si deux objets sont égaux (par-isEqual:
), ils doivent avoir le même valeur de hachage "AND" Si deux objets chaîne sont égaux (comme déterminé par la méthode isEqualToString:), ils doivent avoir la même valeur de hachage. "L'opérateur d'égalité
==
compare uniquement les adresses de pointeur. Lorsque vous créez deux chaînes identiques à l'aide de la@""
syntaxe littérale , le compilateur détecte qu'elles sont égales et ne stocke 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, tout en étant stockées à différents emplacements de mémoire. Par conséquent, vous devez toujours utiliserisEqual:
lors de la comparaison de chaînes.Notez que
isEqual:
etisEqualToString:
renvoie toujours la même valeur, maisisEqualToString:
c'est plus rapide.la source
isEqualToString
: provoquera une exception si le paramètre qui lui est passé l'estnil
. Donc, s'il y a une chance que vous compariez à une chaîne nulle, vous devriez d'abord faire une vérification nulle ou utiliserisEqual:
==
compare les emplacements en mémoire.ptr == ptr2
s'ils pointent tous les deux vers le même emplacement mémoire. Cela fonctionne avec des constantes de chaîne car le compilateur utilise une chaîne réelle pour des constantes de chaîne identiques. Cela ne fonctionnera pas si vous avez des variables avec le même contenu, car elles pointeront vers des emplacements de mémoire différents; utiliserisEqualToString
dans un tel cas.la source
Dans Cocoa, les chaînes sont comparées à l'aide de la
isEqualToString:
méthode de NSString .La comparaison de pointeurs fonctionne dans votre cas car le compilateur est suffisamment doux pour fusionner les deux chaînes littérales pour pointer vers un objet. Il n'y a aucune garantie que deux chaînes identiques partagent une
NSString
instance.la source
NSString
instances distinctes avec un contenu identique:[NSMutableString string] != [NSMutableString string]
==
fonctionnalité. Cependant, si vous supprimez une NSString, attribuez une valeur, puis supprimez une autre NSString comme celle-ci,NSString stringWithFormat:
vous obtenez en fait deux chaînes différentes qui==
échoueront. Vous avez dit qu'il n'y avait aucune garantie que deux instances NSString (pas NSMutableString) partageraient une instance NSString, et j'ai simplement demandé si vous aviez une preuve de cette réclamation afin que je puisse la partager.Un exemple montrant comment la comparaison d'adresses en tant que substitut de la comparaison de chaînes se cassera:
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];
la source
Regardez 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 est susceptible d'utiliser la méthode isEqualToString pour traiter isEquals pour les pointeurs de NSString et de déréférencement, bien qu'il ne l'ait pas fait. Et les pointeurs sont différents, comme vous le voyez.
la source
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"); }
la source