2016-08-18 18 views
0

は、私は次のコードを持っている:NSArrayのインスタンスを作成しましたが、NSArrayではなく__NSArrayIのクラスを作成しましたか?

id anArray = [NSArray arrayWithObjects:@1, @2, nil]; 
NSLog(@"anArrayClass - %@", [anArray class]); 
NSLog(@"NSArrayClass - %@", [NSArray class]); 

をそして、私は両方の出力を期待し、NSArrayですが、出力があることが判明:

2016-08-18 21:08:53.628 TestUse[9279:939745] anArrayClass - __NSArrayI 
2016-08-18 21:08:53.629 TestUse[9279:939745] NSArrayClass - NSArray 

その後、私はCAJTestClassと呼ばれるテストクラスを作成し、インスタンスを作成しますそのクラスの:

id testInstance = [CAJTestClass new]; 
NSLog(@"testInstanceClass - %@", [testInstance class]); 
NSLog(@"cajTestClass - %@", [CAJTestClass class]); 

この時の出力は次のようになります。

2016-08-18 21:08:53.629 TestUse[9279:939745] testInstanceClass - CAJTestClass 
2016-08-18 21:08:53.629 TestUse[9279:939745] cajTestClass - CAJTestClass 

今回は結果が期待通りです。しかし、なぜ[anArray class]__NSArrayIになるのですか?
「効果的なObjective-C」の説明は、NSArrayが「クラスクラスタ」の一部であるということです(これは継承関係を持つ一連のクラスだと思います)。しかし、CAJTestClassNSObjectのサブクラスです。私が間違っている?

編集:すべてのお返事ありがとうございます。しかし、私の疑問はまさに「クラスター」の問題に貢献すれば、私はこの2つのケースで異なる結果になるのですか?

答えて

3

EDITを使用することができます。しかし、私の疑問はまさに「クラスター」の問題に貢献すれば、私はこの2つのケースで異なる結果になるのですか?

テストコードが完全に異なるためです。 NSArrayメソッドを呼び出すと、NSArrayのサブクラスが返されますが、[CAJTestClass new]を呼び出すと、CAJTestClassが返されます。あなたがそれらが同じで作る場合は、同じ結果を得る:

@interface CAJTestClass : NSObject 
+ (instancetype)testClassWithMagic; 
@end 

@interface __MagicTestSubclass : CAJTestClass 
@end 

@implementation CAJTestClass 

+ (instancetype)testClassWithMagic { 
    return [__MagicTestSubclass new]; 
} 
@end 

@implementation __MagicTestSubclass 
@end 

は、今すぐあなたのテストコードを使用して:

id testInstance = [CAJTestClass testClassWithMagic]; 
    NSLog(@"testInstanceClass - %@", [testInstance class]); 
    NSLog(@"cajTestClass - %@", [CAJTestClass class]); 

2016-08-18 09:57:15.126 test[72004:47882338] testInstanceClass - __MagicTestSubclass 
2016-08-18 09:57:15.127 test[72004:47882338] cajTestClass - CAJTestClass 

rmaddyは、さまざまな疑問を持っているし、彼という可能性を提起します正しいかもしれないので、私はそれにも答えます。

[anArray class]は、-classメッセージをインスタンスanArrayに渡した結果です。 -classメッセージを受け取ったときにインスタンスが行う通常のことは、(特定のサブクラスとして)初期化された特定のクラスを返すことです。これは普遍的ではありません(KVOクラスは意図的にこのルールを破り、実行時にクラスを変更することも可能です)が、これは一般的なアプローチです。これは、構造体のポインタisaで、ディスパッチャにどのメソッドセットを使用するかを指示します。実際のインスタンス化されたクラスオブジェクト(__NSArrayI)を取得します。

[NSArray class]は、+classメッセージをクラスオブジェクトNSArrayに渡した結果です。クラスオブジェクトの通常の返事はselfです(そのルールに違反するクラスはわかりませんが、そのルールに違反することはできません)。だから、メッセージを渡したクラスは(NSArray)になります。

+0

OPはなぜ '[anArray class]'と '[NSArray class]'が別の結果を返すのかを知りたいと思っています。 – rmaddy

+0

それは元の質問です(それは他のすべての回答でうまく答えています)。しかし、編集はなぜNSArrayのための1つの方法であったのかをさらに質問しましたが、CAJTestClassの別の方法でした。なぜなら、 'CAJTestClass'の場合は' NSArray'とまったく異なるコードだったからです。 –

+0

いいえ、答えのどれも2つが異なる理由を説明していません。それはすべて '__NSArrayI'が何であるかを説明します。 – rmaddy

3

ソフトウェア開発では、NSArrayとNSMutableArrayだけが心配です。背後には、さまざまなクラスがあります。たとえば、空の配列のシングルトンクラスです。 1つの配列要素を持つ配列のクラス。すべての人がメモリを節約します。なぜなら、人々はトンとトンの簡単な配列を使用するからです。

+2

私は、この裏返しのために、「舞台裏」を参照するために孤立して投票しました。要点は、NSArray arrayWithObjects:は、NSArrayインターフェースを実装しているものは何でも返すことが許されているということです。あなたのコードは、どんなクラスが得られるかを決して気にするべきではありません。 「クラスクラスター」は、通常、initメソッドまたはfactoryメソッドから戻ったものが、allocしたクラスの型である必要はなく、ファクトリメソッドを使用したクラスである必要があることを意味します。通常はサブクラスになります。 – Tommy

1

__NSArrayIは、変更できない「通常の」NSArrayという不変の配列のコードワードです。

__NSArrayMは、可変配列のコードワードです。つまり、NSMutableArrayです。 NSMutableArrayでは、項目を追加および削除できます。

0

__NSArrayIは、初期化後に変更できない不変バージョンのアレイを指します。

0

__NSArrayIは、NSArrayの不変形式を意味します。また、変更可能な形式の__ NSArrayMもあります。変更不可能とは、変更できないということです。この配列内のオブジェクトは変更できません。変更可能な場合は、要素を変更することができます。 Uもこの投稿をチェックアウトすることができます。私はこれもあなたの質問に答えると思います。 What is __NSArrayI and __NSArrayM? How to convert to NSArray?

1

__NSArrayIは、不変のNSArrayのプライベートクラスです。また、可変配列のプライベートクラスである__NSArrayMがあります。どちらも、NSArray

+ arrayWithObjects:のサブクラスである、これはアプリストアの配布のために使用することはできませんプライベートAPIであるとして、あなたはそれについてできることは何もない__NSArrayIを返します。すべてのあなたの答えをありがとう:あなたはあなたのオブジェクトがNSArrayであることを確認したい場合は

あなたは

if ([anArray isKindOfClass:[NSArray class]]){ 
    //blablabla 
} 
関連する問題