2011-10-24 13 views
9

idが弱参照ポインタである理由と、class型ポインタをどのように扱うことができるのか、そして実行時にidに割り当てられるクラスポインタの種類を検出する方法を知りたいのですが。なぜIDは汎用ポインタですか?

答えて

16

なぜ弱い参照ポインタですか?

idは、少なくともARC所有権の意味ではない弱い参照ポインタではありません。 idの型指定されたオブジェクトへの参照が弱いかどうかは、__weak(およびバリエーション)と宣言されている参照と実際に弱い参照をサポートしているオブジェクトのクラスによって異なります。

しかし、idの弱いと入力していると言えますが、ダイナミック/アヒルのタイピングはより正確な説明です。 id型参照にコンパイル時のクラス型情報が含まれていないため、コンパイラは、実行時エラーを引き起こす可能性のある、下位のオブジェクトが指定されたセレクタに応答できるかどうかを判断できません。

どのようなクラス型ポインタを扱うことができますか?

これはthe Objective-C languageの定義の一部です。コンパイラは、すべてのObjective-Cクラスのスーパータイプとしてidを認識し、idを異なる方法で処理します。以下の答えも参照してください。

実行時に、どのタイプのクラスポインタがidに割り当てられているかをどのように検出できますか?

AppleのObjective-Cランタイムでは、オブジェクトに割り当てられたメモリの最初のバイトがそのオブジェクトのクラスを指している必要があります。これはisaポインタとして参照されていますが、これはAppleのランタイムがすべてオブジェクトのクラスを検出する方法です。 idタイプもこの情報を持つように定義されています。実際には、その唯一の属性はisaポインタです。つまり、すべて Objective-Cオブジェクトがこの定義に準拠しています。あなたがid参照を持っているし、参照されたオブジェクトのクラスを発見したい場合

、あなたはそれを-classを送ることができます:

id someObject; 

// Assign something to someObject 

// Log the corresponding class 
Class c = [someObject class]; 
NSLog(@"class = %@", c); 

// Test whether the object is of type NSString (or a subclass of NSString) 
if ([someObject isKindOfClass:[NSString class]]) { 
    NSLog(@"it's a string"); 
} 

Tagged pointersは、この構造の顕著な偏差であり、(一部)そのため、isaポインタに直接アクセスすべきではありません。

7

一般的なオブジェクト型を使用するといいです。あらゆる種類のオブジェクトを保持できるコレクション型や、オブジェクトの種類がわからなくてもオブジェクトで動作するその他の汎用サービスを定義できます。

idを動作させるためのトリックはありません。バイナリレベルでは、すべてのポインタは互換性があります。彼らは単に数値としてメモリアドレスを表します。 idがあらゆるタイプのポインタを受け入れるようにするには、には、通常はポインタ型の一致が必要なコンパイラの規則を無効にするだけです。

id theObject = // ... something 
Class theClass = [theObject class]; 
NSString *className = NSStringFromClass(theClass); 
NSClassDescription *classDescription = [NSClassDescription classDescriptionForClass:theClass]; 

をしかし、それはコードで物事のこれらの種類を行うために必要なことはまれです:

あなたは方法のこれらの種類のid型変数のクラスについての情報を見つけることができます。より頻繁には、id変数が特定のクラスのインスタンスであるかどうかをテストする必要があります。その場合は、そのクラスにキャストし、その型として扱います。

if ([theObject isKindOfClass:[MySpecializedClass class]]) { 
    MySpecializedClass *specialObject = (MySpecializedClass *)theObject; 
    [specialObject doSomethingSpecial]; 
} 

あなたは、クラスを見つけるために-classを使用していたが、それは、あなたはとにかくそのクラスに基づいてオブジェクトを行うことができ、特別な何もない、あなたがについて何も知らないクラスを返された場合。したがって、あなたが知っているクラスと一致するかどうかをチェックするだけで、そのクラスのために特別な処理を行うつもりならば、何もする必要はありません。

isKindOfClassの代わりにisMemberOfClassを使用することがあります。正確に一致するか、サブクラスを含めるかによって異なります。

3

idという内部構造を見つけるために、ヘッダファイルobjc/objc.hを調べる価値があります。

typedef struct objc_class *Class; 
typedef struct objc_object { 
    Class isa; 
} *id; 


typedef struct objc_selector *SEL;  
typedef id   (*IMP)(id, SEL, ...); 
関連する問題