Причина, по которой ==
работает, заключается в сравнении указателей. Когда вы определяете константу NSString
using @""
, компилятор унифицирует ссылку. Когда одни и те же константы определены в других местах вашего кода, все они будут указывать на одно и то же фактическое место в памяти.
При сравнении NSString
экземпляров следует использовать isEqualToString:
метод:
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];
Редактировать:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
больше не создает новую ссылку, вам понадобится initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
myString3
указатель на константу"foo"
в целях оптимизации, поэтому обычно все три эти переменные будут указывать на одно и то же место в памяти. Это верно как для gcc, так и для clang (с параметрами по умолчанию). Попробуйте скомпилировать это: gist.github.com/578568isEqual:
действительно выполняет полное сравнение строк и возвращает тот же результат, что иisEqualToString
потому, что ссылка на протокол NSObject и ссылка на класс NSString явно указывают (соответственно): «Если два объекта равны (по-isEqual:
), они должны иметь одинаковые хэш-значение «И» Если два строковых объекта равны (как определено методом isEqualToString:), они должны иметь одинаковое хеш-значение ».Оператор равенства
==
сравнивает только адреса указателей. Когда вы создаете две идентичные строки с использованием буквального@""
синтаксиса, компилятор обнаружит, что они равны, и сохранит данные только один раз. Следовательно, два указателя указывают на одно и то же место. Однако строки, созданные другими способами, могут содержать идентичные данные, но при этом храниться в разных ячейках памяти. Следовательно, вы всегда должны использоватьisEqual:
при сравнении строк.Обратите внимание, что
isEqual:
иisEqualToString:
всегда возвращает одно и то же значение, ноisEqualToString:
быстрее.источник
isEqualToString
: вызовет исключение, если переданный ему параметр имеет значениеnil
. Так что, если есть шанс, что вы сравниваете строку с нулем, вам следует либо сначала выполнить проверку на ноль, либо использоватьisEqual:
==
сравнивает места в памяти.ptr == ptr2
если они оба указывают на одно и то же место в памяти. Это происходит при работе со строковыми константами, потому что компилятор использует одну фактическую строку для идентичных строковых констант. Это не сработает, если у вас есть переменные с одинаковым содержимым, потому что они будут указывать на разные места в памяти; использоватьisEqualToString
в таком случае.источник
В Какао строки сравниваются с помощью
isEqualToString:
метода NSString .Сравнение указателей работает в вашем случае, потому что компилятор достаточно мягкий, чтобы объединить два строковых литерала, чтобы указать на один объект. Нет гарантии, что две одинаковые строки используют один
NSString
экземпляр.источник
NSString
экземпляра с одинаковым содержанием:[NSMutableString string] != [NSMutableString string]
==
функциональность. Однако, если вы удалите одну NSString, назначите значение, а затем удалите другую 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 для обработки isEquals для указателей NSString и разыменования, хотя этого и не должно было. И указатели, как видите, разные.
источник
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"); }
источник