Понимание сравнения NSString

Оба следующих сравнения оцениваются как true:

1)

@"foo" == @"foo";

2)

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

Однако существуют определенные моменты, когда два NSString не могут сравниваться с использованием оператора равенства, а вместо этого требуется [myString1 isEqualToString:myString2]. Может кто-то пролить свет на это?

Ответ 1

Причина, по которой работает ==, - это сравнение указателей. Когда вы определяете константу NSString с помощью @"", компилятор идентифицирует ссылку. Когда одни и те же константы определены в других местах вашего кода, все они указывают на то же самое фактическое местоположение в памяти.

При сравнении экземпляров 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];

Ответ 2

Оператор равенства == сравнивает только адреса указателей. Когда вы создаете две идентичные строки, используя синтаксис literal @"", компилятор обнаружит, что они равны, и только сохраняет данные один раз. Следовательно, два указателя указывают на одно и то же место. Однако строки, созданные другими средствами, могут содержать идентичные данные, но сохраняются в разных ячейках памяти. Следовательно, вы должны всегда использовать isEqual: при сравнении строк.

Обратите внимание, что isEqual: и isEqualToString: всегда возвращают одно и то же значение, но isEqualToString: быстрее.

Ответ 3

== сравнивает местоположения в памяти. ptr == ptr2, если они оба указывают на одну и ту же ячейку памяти. Это происходит с строковыми константами, потому что компилятор использует одну фактическую строку для идентичных строковых констант. Это не сработает, если у вас есть переменные с одним и тем же содержимым, потому что они будут указывать на разные ячейки памяти; используйте isEqualToString в таком случае.

Ответ 4

В Cocoa строки сравниваются с использованием метода NSString isEqualToString:.

Сравнение указателей работает в вашем случае, потому что компилятор достаточно мягкий, чтобы объединить два строковых литерала, чтобы указать на один объект. Там нет гарантии, что две идентичные строки имеют один экземпляр NSString.

Ответ 5

Пример, демонстрирующий, как нарушение адреса в сравнении с суррогатом для сравнения строк:

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

Ответ 6

Посмотрите этот пример:

NSString *myString1 = @"foo";
NSMutableString *myString2 = [[NSMutableString stringWithString:@"fo"] stringByAppendingString: @"o"];

NSLog(@"isEquality: %@", ([myString1 isEqual:myString2][email protected]"+":@"-")); //YES
NSLog(@"isEqualToStringity: %@", ([myString1 isEqualToString:myString2][email protected]"+":@"-")); //YES
NSLog(@"==ity: %@", ((myString1 == myString2)[email protected]"+":@"-")); // NO

Итак, компилятор, скорее всего, будет использовать метод isEqualToString для обработки isEquals для указателей NSString и указателей разыменования, хотя этого не было. И указатели разные, как вы видите.

Ответ 7

  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 ([email protected]"hello1") {

        NSLog(@"Both String are equal");
    }
    else{
        NSLog(@"Both String not are equal");

    }