以下两个比较的评估结果均为true:
1)
@"foo" == @"foo";
2)
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
myString1 == myString2;
但是,在某些情况下,肯定NSString
无法使用相等运算符比较两个s,而是必须使用两个运算符[myString1 isEqualToString:myString2]
。有人可以阐明这一点吗?
Answers:
之所以==
起作用,是因为指针比较。当你定义一个恒定的NSString
使用@""
,编译器uniquifies参考。当在代码的其他位置定义相同的常量时,它们都将指向内存中的相同实际位置。
比较NSString
实例时,应使用以下isEqualToString:
方法:
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];
编辑:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
不再创建新参考,您将需要initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
isEqual:
实际上确实进行了完整的字符串比较并返回了相同的结果,isEqualToString
因为NSObject Protocol Reference和NSString Class Reference分别明确指定:“如果两个对象相等,则-isEqual:
它们必须具有相同的“ AND”如果两个字符串对象相等(由isEqualToString:方法确定),则它们必须具有相同的哈希值。”
相等运算符==
仅比较指针地址。使用文字@""
语法创建两个相同的字符串时,编译器将检测到它们相等,并且仅将数据存储一次。因此,两个指针指向相同的位置。但是,通过其他方式创建的字符串可能包含相同的数据,但仍存储在不同的存储位置。因此,比较字符串时应始终使用isEqual:
。
需要注意的是isEqual:
,并isEqualToString:
始终返回相同的值,但isEqualToString:
速度更快。
isEqualToString
:如果传递给它的参数为,将导致异常nil
。因此,如果有机会与nil字符串进行比较,则应该先进行nil检查还是使用isEqual:
==
比较内存中的位置。ptr == ptr2
如果它们都指向相同的内存位置。这恰好适用于字符串常量,因为编译器碰巧将一个实际的字符串用于相同的字符串常量。它不会,如果你有相同的内容变量的工作,因为他们会指向不同的内存位置; 使用isEqualToString
在这样的情况下。
在可可中,使用NSString的isEqualToString:
方法比较字符串。
指针比较适用于您的情况,因为编译器足够柔和,可以合并两个字符串文字以指向一个对象。不能保证两个相同的字符串共享一个NSString
实例。
NSString
具有相同内容的两个不同实例:[NSMutableString string] != [NSMutableString string]
==
功能。但是,如果您用delcare一个NSString,分配一个值,然后用delcare这样的另一个NSString,NSString stringWithFormat:
则实际上您会得到两个不同的字符串,它们==
将失败。您说不能保证两个NSString(不是NSMutableString)实例将共享一个NSString实例,我只是问您是否有该主张的证据,以便我可以共享它。
一个示例,说明如何将地址比较作为字符串比较的替代方法:
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];
看看这个例子:
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
因此,编译器可能会使用isEqualToString方法来处理NSString和解引用指针的isEquals,尽管它不必这样做。如您所见,指针是不同的。
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");
}
myString3
指向常量"foo"
,因此通常所有这三个变量都指向相同的内存位置。对于gcc和clang(使用默认选项)都是如此。尝试编译如下:gist.github.com/578568