84

次の比較は両方とも true と評価されます。

1)

@"foo" == @"foo";

2)

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

ただし、等値演算子を使用して 2 つNSStringの s を比較できない場合があり、[myString1 isEqualToString:myString2]代わりに必要になります。誰かがこれに光を当てることができますか?

4

7 に答える 7

168

動作する理由==は、ポインタの比較のためです。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"];
于 2010-09-13T19:11:09.843 に答える
13

等価演算子==は、ポインタアドレスのみを比較します。リテラル@""構文を使用して2つの同一の文字列を作成すると、コンパイラはそれらが等しいことを検出し、データを1回だけ保存します。したがって、2つのポインターは同じ場所を指します。ただし、他の方法で作成された文字列には、同じデータが含まれていても、異なるメモリ位置に格納されている場合があります。したがって、文字列を比較するときは常に使用する必要があります。isEqual:

isEqual:isEqualToString:は常に同じ値を返しますが、より高速であることに注意してくださいisEqualToString:

于 2010-09-13T19:11:45.900 に答える
10

==メモリ内の場所を比較します。ptr == ptr2両方が同じメモリ位置を指している場合。コンパイラはたまたま同一の文字列定数に対して1つの実際の文字列を使用するため、これは文字列定数で機能します。同じ内容の変数がある場合、それらは異なるメモリ位置を指すため、機能しません。そのような場合に使用isEqualToStringします。

于 2010-09-13T19:12:21.687 に答える
6

Cocoaでは、文字列はNSStringのisEqualToString:メソッドを使用して比較されます。

コンパイラは2つの文字列リテラルをマージして1つのオブジェクトを指すのに十分穏やかであるため、ポインタ比較はこの場合に機能します。2つの同一の文字列が1つのNSStringインスタンスを共有するという保証はありません。

于 2010-09-13T19:10:30.877 に答える
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];
于 2012-01-17T10:42:55.570 に答える
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 を処理し、ポインターを逆参照する可能性がありますが、そうする必要はありませんでした。ご覧のとおり、ポインターは異なります。

于 2017-04-17T17:30:17.217 に答える