NSString 비교 이해


83

다음 비교는 모두 참으로 평가됩니다.

1)

@"foo" == @"foo";

2)

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

그러나 NSString항등 연산자를 사용하여 두 s를 비교할 수없는 경우가 있으며 [myString1 isEqualToString:myString2]대신 필요합니다. 누군가 이것에 대해 밝힐 수 있습니까?

답변:


165

이유 ==일 때문에 포인터 비교입니다. 를 사용하여 상수 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];

편집하다:

NSString *myString3 = [[NSString alloc] initWithString:@"foo"]; 
// this is same with @"foo"

initWithString:더 이상 새 참조를 만들지 않습니다. initWithFormat,

NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];

6
대부분의 컴파일러는 최적화로 myString3상수에 대한 포인터 도 만들 "foo"것이므로 일반적으로 이러한 세 가지 변수는 모두 동일한 메모리 위치를 가리 킵니다. 이는 gcc 및 clang 모두에 해당됩니다 (기본 옵션 사용). 이 컴파일 시도 gist.github.com/578568
mipadi

그래서 어떻게 NSString 변수가 @ "..."와 똑같이 동작하도록 만들 수 있습니까? 내가 묻는 이유는 지금 내 코드에서 b / c 상수 @ ".."가 작동하지만 NSString 변수로 바꾸 자마자 충돌이 발생합니다. 여기를
abbood

2
+1, Just to add : isEqual:실제로 전체 문자열 비교를 수행하고 다음과 같은 결과를 반환합니다 isEqualToString. NSObject의 프로토콜 참조 하고 있는 NSString 클래스 참조가 명시 적으로 (각각) 지정을 "두 개체가 (가 같은 경우 -isEqual:)가 동일해야합니다 해시 값 "AND"두 문자열 개체가 같으면 (isEqualToString : 메서드에 의해 결정됨) 동일한 해시 값을 가져야합니다. "
Ephemera 2013 년

13

항등 연산자 ==는 포인터 주소 만 비교합니다. 리터럴 @""구문을 사용하여 두 개의 동일한 문자열을 만들면 컴파일러는 두 문자열 이 같은지 감지하고 데이터를 한 번만 저장합니다. 따라서 두 포인터는 동일한 위치를 가리 킵니다. 그러나 다른 방법으로 생성 된 문자열은 동일한 데이터를 포함 할 수 있지만 다른 메모리 위치에 저장됩니다. 따라서 문자열을 비교할 때 항상 사용해야 isEqual:합니다.

참고 isEqual:isEqualToString:항상 같은 값을 반환하지만 isEqualToString:더 빠릅니다.


2
또한 isEqualToString: 전달 된 매개 변수가 다음과 같으면 예외가 발생합니다 nil. 당신이 전무 문자열로 비교하는 기회가 있다면 그래서, 당신도 처음 전무 확인을하거나 사용한다isEqual:
샌디 채프먼

10

==메모리의 위치를 ​​비교합니다. ptr == ptr2둘 다 동일한 메모리 위치를 가리키는 경우. 이것은 컴파일러가 동일한 문자열 상수에 대해 하나의 실제 문자열 을 사용하기 때문에 문자열 상수와 함께 작동 합니다. 그것은 하지 않습니다 당신이 같은 내용 변수가있는 경우 서로 다른 메모리 위치를 가리키는 것이기 때문에, 작동; 사용 isEqualToString등의 경우이다.


"같은 내용의 변수가 있으면 작동하지 않습니다"라는 의미의 예를 들어 계몽 할 수 있습니까?
Logicsaurus Rex 2015-08-20

6

Cocoa에서 문자열은 NSString을 사용하여 비교됩니다. isEqualToString: 방법을 .

포인터 비교는 컴파일러가 두 문자열 리터럴을 병합하여 하나의 객체를 가리 키도록 충분히 부드럽기 때문에 귀하의 경우에 작동합니다. 두 개의 동일한 문자열이 하나의 NSString인스턴스를 공유한다는 보장은 없습니다 .


이것에 대한 공식적인 언급이 있습니까? "두 개의 동일한 문자열이 하나의 NSString 인스턴스를 공유한다는 보장은 없습니다."
Logicsaurus Rex 2015 년

@ user3055655 참조가 필요하지 않습니다. NSString동일한 콘텐츠를 가진 두 개의 별개 인스턴스 를 만드는 코드를 쉽게 작성할 수 있습니다 .[NSMutableString string] != [NSMutableString string]
Nikolai Ruhe 2015-08-20

@ user3055655 문자열 리터럴에 대한 내 주장이 사실이 아니라는 것을 의미하는 경우 : 앱 및 테스트 번들과 같은 두 번들의 리터럴을 사용해보십시오.
Nikolai Ruhe 2015 년

동료에게 보여줄 무언가를 원했습니다. 변경 가능한 문자열이 같을 것으로 기대하지는 않지만 NSString의 두 인스턴스를 선언하고 일부 @ "문자열 값"을 할당하면 항상 ==기능이 보장 됩니다. 그러나 하나의 NSString을 delcare하고 값을 할당 한 다음 이와 같이 다른 NSString을 delcare NSString stringWithFormat:하면 실제로 ==실패 할 두 개의 다른 문자열을 얻 습니다. 두 개의 NSString (NSMutableString이 아님) 인스턴스가 하나의 NSString 인스턴스를 공유 할 것이라는 보장이 없다고 말씀 하셨고, 공유 할 수 있도록 해당 주장에 대한 증거가 있는지 간단히 물었습니다.
Logicsaurus 렉스

@ user3055655 내가 말했듯이 별개의 번들에서 리터럴을 사용해보십시오.
Nikolai Ruhe 2015 년

3

문자열 비교를위한 대리자로서의 주소 비교가 어떻게 중단되는지 보여주는 예 :

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

0

이 예를 확인하십시오.

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를 처리 할 가능성이 높습니다. 보시다시피 포인터가 다릅니다.


-1
  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");

    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.