了解NSString比较


83

以下两个比较的评估结果均为true:

1)

@"foo" == @"foo";

2)

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

但是,在某些情况下,肯定NSString无法使用相等运算符比较两个s,而是必须使用两个运算符[myString1 isEqualToString:myString2]。有人可以阐明这一点吗?

Answers:


165

之所以==起作用,是因为指针比较。当你定义一个恒定的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"];

6
大多数编译器还将优化myString3指向常量"foo",因此通常所有这三个变量都指向相同的内存位置。对于gcc和clang(使用默认选项)都是如此。尝试编译如下:gist.github.com/578568
mipadi

因此,如何使NSString变量的行为完全类似于@“ ...”?我想问的原因是在我的代码B / C,现在恒@“..”的作品,但只要我有一个NSString变量替换它崩溃..看到这里
abbood

2
+1,仅需添加:isEqual:实际上确实进行了完整的字符串比较并返回了相同的结果,isEqualToString因为NSObject Protocol ReferenceNSString Class Reference分别明确指定:“如果两个对象相等,则-isEqual:它们必须具有相同的“ AND”如果两个字符串对象相等(由isEqualToString:方法确定),则它们必须具有相同的哈希值。”
Ephemera 2013年

13

相等运算符==仅比较指针地址。使用文字@""语法创建两个相同的字符串时,编译器将检测到它们相等,并且仅将数据存储一次。因此,两个指针指向相同的位置。但是,通过其他方式创建的字符串可能包含相同的数据,但仍存储在不同的存储位置。因此,比较字符串时应始终使用isEqual:

需要注意的是isEqual:,并isEqualToString:始终返回相同的值,但isEqualToString:速度更快。


2
另请注意isEqualToString:如果传递给它的参数为,将导致异常nil。因此,如果有机会与nil字符串进行比较,则应该先进行nil检查还是使用isEqual:
Sandy Chapman 2015年

10

==比较内存中的位置。ptr == ptr2如果它们都指向相同的内存位置。这恰好适用于字符串常量,因为编译器碰巧将一个实际的字符串用于相同的字符串常量。它不会,如果你有相同的内容变量的工作,因为他们会指向不同的内存位置; 使用isEqualToString在这样的情况下。


您能举例说明“如果变量的内容相同,它就行不通”是什么意思?
Logicsaurus Rex

6

在可可中,使用NSString的isEqualToString:方法比较字符串。

指针比较适用于您的情况,因为编译器足够柔和,可以合并两个字符串文字以指向一个对象。不能保证两个相同的字符串共享一个NSString实例。


您对此有官方参考吗?“不能保证两个相同的字符串共享一个NSString实例。”
Logicsaurus Rex

@ user3055655我不需要参考:您可以轻松编写代码来创建NSString具有相同内容的两个不同实例:[NSMutableString string] != [NSMutableString string]
Nikolai Ruhe 2015年

@ user3055655如果您的意思是我对字符串文字的主张不成立:请尝试使用两个捆绑软件(例如应用程序及其测试捆绑软件)中的文字。
Nikolai Ruhe 2015年

我只是想向同事们展示一些东西。我不希望可变的字符串相等,但是声明两个NSString实例并分配一些@“ string value”总是可以保证==功能。但是,如果您用delcare一个NSString,分配一个值,然后用delcare这样的另一个NSString,NSString stringWithFormat:则实际上您会得到两个不同的字符串,它们==将失败。您说不能保证两个NSString(不是NSMutableString)实例将共享一个NSString实例,我只是问您是否有该主张的证据,以便我可以共享它。
Logicsaurus Rex 2015年

@ user3055655正如我说的,请尝试使用不同包中的文字。
Nikolai Ruhe

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

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.