id
とはどう違いvoid *
ますか?
7 に答える
void *
「型付けされていない/不明な内容を持つメモリのランダムなチャンクへの参照」を意味します
id
「未知のクラスのランダムなObjective-Cオブジェクトへの参照」を意味します
追加のセマンティックの違いがあります。
GC Only または GC Supported モードでは、コンパイラは type の参照に対して書き込みバリアを発行しますが、 type に対しては発行し
id
ませんvoid *
。構造体を宣言する場合、これは重大な違いになる可能性があります。が実際にオブジェクトである場合、 iVar を like として宣言void *_superPrivateDoNotTouch;
すると、オブジェクトの早期リープが発生します。_superPrivateDoNotTouch
そうしないでください。型の参照でメソッドを呼び出そうとすると
void *
、コンパイラの警告が表示されます。型でメソッドを呼び出そうとすると、呼び出されているメソッドがコンパイラによって認識される宣言
id
のいずれでも宣言されていない場合にのみ警告が表示されます。@interface
したがって、オブジェクトを として参照するべきではありませんvoid *
。id
同様に、型付き変数を使用してオブジェクトを参照することは避けるべきです。できる限り具体的なクラス型参照を使用してください。コンパイラは、少なくとも、その参照に対するメソッド呼び出しのより良い検証を提供できるため、NSObject *
よりも優れています。id
の一般的かつ有効な用途の 1 つvoid *
は、他の API を介して渡される不透明なデータ参照として使用することです。
sortedArrayUsingFunction: context:
次の方法を検討してくださいNSArray
。
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
ソート関数は次のように宣言されます。
NSInteger mySortFunc(id left, id right, void *context) { ...; }
この場合、NSArray は、引数として渡されたcontext
ものをそのままメソッドに渡しcontext
ます。NSArray に関する限り、これはポインター サイズのデータの不透明な塊であり、目的に応じて自由に使用できます。
言語にクロージャー型の機能がない場合、これが関数でデータの塊を運ぶ唯一の方法です。例; mySortFunc() を条件付きで大文字と小文字を区別または区別しないように並べ替え、スレッドセーフでもある場合は、大文字と小文字を区別するインジケーターをコンテキストで渡し、途中でキャストする可能性があります。
脆弱でエラーが発生しやすいですが、唯一の方法です。
ブロックはこれを解決します -- ブロックは C のクロージャです。ブロックは Clang で利用できます -- http://llvm.org/であり、Snow Leopard ( http://developer.apple.com/library/ios/documentation/Performance /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf )。
id は目的の C オブジェクトへのポインターであり、void* は何かへのポインターです。
id は、不明なメソッドの呼び出しに関連する警告もオフにします。たとえば、次のようになります。
[(id)obj doSomethingWeirdYouveNeverHeardOf];
不明なメソッドに関する通常の警告は表示されません。もちろん、obj が nil でないか、実際にそのメソッドを実装していない限り、実行時に例外が発生します。
返されたオブジェクトが Cocoa オブジェクトであることを少なくとも確認するため、 orよりも優先してNSObject*
orを使用する必要があります。これにより、retain/release/autorelease などのメソッドを安全に使用できます。id<NSObject>
id
id
Objective-C オブジェクトへのポインタです。何かvoid *
へのポインタです。の代わりに を使用できますが、コンパイラの警告がまったく表示されないため、お勧めしません。void *
id
stackoverflow.com/questions/466777/whats-the-difference-before-declaring-a-variable-id-and-nsobjectとunixjunkie.blogspot.com/2008/03/id-vs-nsobject-vsを見たいと思うかもしれません-id.html .
メソッドの戻り値の型が の場合、id
任意の Objective-C オブジェクトを返すことができます。
void
つまり、メソッドは何も返しません。
void *
単なるポインタです。ポインターが指すアドレスの内容を編集することはできません。
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
上記のコードは objc.h からのものであるため、id は objc_object 構造体のインスタンスであり、isa ポインターは任意の Objective C クラス オブジェクトとバインドできるように見えますが、void* は型指定されていないポインターです。
私の理解では、 id はオブジェクトへのポインターを表し、 void * は、それを使用したい型にキャストする限り、実際には何でも指すことができます
既に述べたことに加えて、コレクションに関連するオブジェクトとポインターには違いがあります。たとえば、何かを NSArray に入れたい場合、(「id」型の) オブジェクトが必要であり、そこで (「void *」型の) 生データ ポインターを使用することはできません。コレクション内で使用するために「id」タイプ[NSValue valueWithPointer:rawData]
に変換するために使用できます。void *rawDdata
一般に、「id」はより柔軟で、それに関連付けられたオブジェクトに関連するより多くのセマンティクスを持っています。Objective C の id タイプを説明する例が他にもあります。