Powodem, dla którego ==
działa, jest porównanie wskaźników. Podczas definiowania stałej NSString
przy użyciu @""
kompilator ujednolica odwołanie. Gdy te same stałe są zdefiniowane w innych miejscach w kodzie, wszystkie będą wskazywać to samo rzeczywiste miejsce w pamięci.
Porównując NSString
instancje, należy skorzystać z isEqualToString:
metody:
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];
Edytować:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:
nie tworzy już nowego odniesienia, będziesz potrzebować initWithFormat
,
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
myString3
wskaźnik do stałej"foo"
jako optymalizację, więc ogólnie wszystkie trzy zmienne będą wskazywać na tę samą lokalizację w pamięci. Dotyczy to zarówno gcc, jak i clang (z domyślnymi opcjami). Spróbuj skompilować to: gist.github.com/578568isEqual:
faktycznie wykonuje pełne porównanie ciągów i zwraca ten sam wynik,isEqualToString
ponieważ odniesienie do protokołu NSObject i odniesienie do klasy NSString wyraźnie określają (odpowiednio): "Jeśli dwa obiekty są równe (o-isEqual:
), muszą mieć to samo wartość skrótu „AND” Jeśli dwa obiekty typu string są równe (zgodnie z metodą isEqualToString:), muszą mieć tę samą wartość skrótu ”.Operator równości
==
porównuje tylko adresy wskaźników. Gdy utworzysz dwa identyczne ciągi przy użyciu@""
składni literału , kompilator wykryje, że są one równe i zapisze dane tylko raz. Stąd te dwa wskaźniki wskazują na tę samą lokalizację. Jednak łańcuchy utworzone w inny sposób mogą zawierać identyczne dane, ale być przechowywane w różnych lokalizacjach pamięci. Dlatego należy zawsze używaćisEqual:
podczas porównywania ciągów.Zwróć uwagę
isEqual:
iisEqualToString:
zawsze zwracaj tę samą wartość, aleisEqualToString:
jest szybsza.źródło
isEqualToString
: spowoduje wyjątek, jeśli przekazany mu parametr tonil
. Jeśli więc istnieje szansa, jesteś porównując do zera ciąg, należy albo zrobić nil pierwszy czek lub wykorzystanieisEqual:
==
porównuje lokalizacje w pamięci.ptr == ptr2
jeśli oba wskazują na to samo miejsce w pamięci. Dzieje się tak ze stałymi łańcuchowymi, ponieważ kompilator używa jednego rzeczywistego ciągu dla identycznych stałych łańcuchowych. To nie będzie działać, jeśli masz zmienne o tych samych treści, ponieważ będą one wskazywać na różnych miejscach pamięci; używaćisEqualToString
w takim przypadku.źródło
W kakao struny są porównywane za pomocą
isEqualToString:
metody NSString .Porównanie wskaźników działa w twoim przypadku, ponieważ kompilator jest wystarczająco delikatny, aby połączyć dwa literały ciągów, aby wskazywały na jeden obiekt. Nie ma gwarancji, że dwa identyczne ciągi współużytkują jedną
NSString
instancję.źródło
NSString
instancje z identyczną zawartością:[NSMutableString string] != [NSMutableString string]
==
funkcjonalność. Jednakże, jeśli usuniesz jeden NSString, przypiszesz wartość, a następnie usuniesz inny NSString w ten sposóbNSString stringWithFormat:
, w rzeczywistości otrzymasz dwa różne łańcuchy, które==
będą się nie powieść. Powiedziałeś, że nie ma gwarancji, że dwie instancje NSString (nie NSMutableString) będą współużytkować jedną instancję NSString, a ja po prostu zapytałem, czy masz jakiś dowód na to twierdzenie, abym mógł się nim podzielić.Przykład pokazujący, w jaki sposób porównanie adresów jako surogat porównania ciągów nie działa:
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];
źródło
Sprawdź ten przykład:
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
Tak więc kompilator prawdopodobnie użyje metody isEqualToString do przetworzenia isEquals dla wskaźników NSString i wyłuskiwania, chociaż nie musiał tego robić. Jak widać, wskaźniki są różne.
źródło
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"); }
źródło