2012-02-06 8 views
1

可能性の重複:
Understanding NSString comparison in Objective-CNSStringが等号で動作するのはなぜですか?

はちょうどアイデンティティ対平等についてまで読んでいたと私は私にObjCコード内の文字列を比較するとき、私はいくつかの等号を使用してきたことに気づきました。奇妙なことは、それが実際に時々から機能することです、なぜ私は不思議に思っていました。

http://www.karlkraft.com/index.php/2008/01/07/equality-vs-identity/

私は、コードの2枚、1つの作業があり、一つはしません。

働く。ここで私は '名前'と呼ばれるNSStringプロパティを持つ 'カテゴリ'と呼ばれるオブジェクトを持っています。

@property (nonatomic, retain) NSString *name; 

私は 'Catergory'ポインタを渡し、ここで等号を使用すると完全に機能します。

-(void)addCategoryToStorage:(Category*)newcategory { 
     if(newcategory.name != @"All") { // this works 

NON WORKING。ここでは、NSFileManager呼び出しの出力を使用します。

NSArray *dirContent = [self.fileManager 
         contentsOfDirectoryAtPath:@"MyFiles" 
         error:nil]; 

私は、配列内のNSStringsの上で比較してみてください:

for(int i = 0; i < [dirContent count]; i++) { 
    if([dirContent objectAtIndex:i] == @"MyFile") // This will never be True 

だから私の質問があり、これら二つのNSStringのポインタがとても違った仕事と理由がどうなりますか?私は "=="を使用すべきではないが、現時点では知っているが、なぜそれが時にはうまくいくのか不思議だ。

私はそれらのデバッグの違いに気づいた。最初のケースでは、 "newcategory"の "name"が(__NSCFConstantString *)と表示され、値を表示していました。 何らかの理由で、 "dirContent"配列に値が表示されない2つの(__NSString *)オブジェクトが含まれています。

これは別の疑問を提起します。最初のケースのNSStringを定数にするのは何ですか?私はそれを関数に渡すと、それがどのように作成されるかと何かがあるようです。関数に渡すNSStringプロパティを持つ新しいオブジェクトを割り当てると、関数はそれを定数(オブジェクトのNSStringプロパティ)とみなします。しかし、オブジェクトがリストに格納されているときに、[array objectAtIndex:index]を関数に渡すことで関数を取得しても、関数は定数(オブジェクトのNSStringプロパティ)として取得されません。

ありがとうございます!

答えて

5

ポインターが同じオブジェクトを指しているときに機能することがあります。

コードに文字列リテラルがある場合は、実際にはNSStringの静的に割り当てられたオブジェクトです。コード内の任意のポイントで、この文字列値を参照する場合は、実際には同じポインタを使用しています。

@"abc"コード内の複数のポイントに文字列リテラルがある場合、コンパイラは1つのインスタンスにのみ配置し、この1つのインスタンスへのポインタを使用します。

これはなぜ@"abc" == @"abc"を説明します。

あなたの例を取る:あなたが行うならば

newcategory.name = @"All"; 

ウィルない作品:

if(newcategory.name != @"All") 

はあなたがやったあなたのコードの中でいくつかの点であれば動作します

newcategory.name = [NSString stringWithFormat:@"%c%c%c",'A','l','l']; 

その最後のケースでは、新しい文字列を明示的に割り当てるためです。ちょうどテスト

編集は、この例では、欠陥がした

newcategory.name = [NSString stringWithString:@"All"]; 

あなたは NStringは、常に「==と連携@"All"

+3

技術用語は* string interning *です。 –

+1

コンパイラは[NSString stringWithString:@ "All"]と@ "All"の間に違いはありませんか? – chikuba

+0

コンパイラが文字列を定数にする場合はどうですか?私はCategoryポインタを提供する2つの関数を持っています。また、NSStringは定数であることもあります。 – chikuba

0

==と比較すると、文字列自体を比較していないため、ポインタの値を文字列と比較しています。あなたのコードに文字列リテラルを宣言すると、実行可能ファイルのdata segmentに格納されます。複数の文字列変数が同じ文字列リテラルを指している場合、それらは同じメモリ位置を指している可能性があります。

ファイルから文字列を読み込むと、ポインタは実行可能ファイルのデータセグメントから来ていない可能性があるため、等価にすることはできません。

たとえば、2つの文字列リテラルasdfは、多くの場合、実行可能ファイルに1回だけ格納されるため、ポインタの値は等しくなります。これはコンパイラによって実行される最適化であり、常に機能するとは限りません。

NSString* someVariable = @"asdf"; 

if(someVariable == @"asdf") 
    NSLog(@"They are equal!"); 
0

に同じポインタを持っていますので、これを離れて最適化されているので、 2つのポインタを比較してEXACT SAMEオブジェクトを参照しているかどうかを確認したい場合は、「sign」を使用します。

一般に、短いリテラルは、@ "ABC" == @ "ABC"となるような方法でプールされますが、それらのリテラルのいずれかが別のクラスにあってもそうです。

しかし、それにはカウントしないでください。

+0

私はそれを認識しています。Atm私は2つのNSStringの間に最大の違いがあることを知りたいのですが、コンパイラがオブジェクトプロパティの文字列をconstに変えることもあるのです。 – chikuba

+1

未知のまま残されているミステリーがいくつかあります。 ;)(実際には、私はすべての詳細を理解していませんが、Objective-Cでは、NSStringのようなオブジェクトは、それがどのように作成されたかによって、いくつかの異なる基底クラスの1つになることがあります。 NSStringは*常に*定数であり、その基底クラスに関係なく、適切なすべてのメソッド/セレクタに正しく応答します。 –

関連する問題