web-dev-qa-db-ja.com

Objective-C:idとvoidの違い*

idvoid *の違いは何ですか?

167
mk12

void *は、「型付けされていない/不明なコンテンツを含むランダムなチャンクへの参照」を意味します

idは、「不明なクラスのランダムなObjective-Cオブジェクトへの参照」を意味します

追加のセマンティックの違いがあります。

  • GC OnlyモードまたはGC Supportedモードでは、コンパイラはid型の参照に対して書き込みバリアを発行しますが、void *型に対しては発行しません。構造を宣言するとき、これは重大な違いになる可能性があります。 void *_superPrivateDoNotTouch;が実際にオブジェクトである場合、_superPrivateDoNotTouchのようなiVarを宣言すると、オブジェクトが早まって刈り取られます。それをしないでください。

  • void *型の参照でメソッドを呼び出そうとすると、コンパイラの警告が発生します。

  • id型でメソッドを呼び出そうとすると、呼び出されているメソッドがコンパイラによって認識される@interface宣言のいずれでも宣言されていない場合にのみ警告されます。

したがって、オブジェクトをvoid *として参照しないでください。同様に、id型付き変数を使用してオブジェクトを参照することは避けてください。できる限り具体的なクラス型付き参照を使用してください。 NSObject *でもidよりも優れています。これは、少なくともコンパイラがその参照に対するメソッド呼び出しの検証を改善できるためです。

void *の一般的かつ有効な使用法の1つは、他のAPIを介して渡される不透明なデータ参照としてです。

NSArraysortedArrayUsingFunction: context:メソッドを検討してください。

- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;

ソート関数は次のように宣言されます。

NSInteger mySortFunc(id left, id right, void *context) { ...; }

この場合、NSArrayはcontext引数として渡したものをcontext引数としてメソッドに渡すだけです。 NSArrayに関する限り、ポインタサイズのデータ​​の不透明な塊であり、目的に応じて自由に使用できます。

言語にクロージャー型の機能がない場合、これは関数で大量のデータを運ぶ唯一の方法です。例; mySortFunc()で大文字と小文字を区別するか、大文字と小文字を区別しないように条件付きでソートし、スレッドセーフでもある場合は、コンテキストでis-case-sensitiveインジケーターを渡します。

脆弱でエラーが発生しやすいが、唯一の方法。

ブロックはこれを解決します-ブロックはCのクロージャーです。Clangで利用可能です- http://llvm.org/ であり、Snow Leopardで普及しています( http:// developer。 Apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf )。

234
bbum

idはObjective Cオブジェクトへのポインタであり、void *は何かへのポインタです。

idは、不明なmthodsの呼び出しに関連する警告もオフにします。たとえば、

[(id)obj doSomethingWeirdYouveNeverHeardOf];

未知のメソッドに関する通常の警告を表示しません。もちろん、objがnilであるか、実際にそのメソッドを実装していない限り、実行時に例外が発生します。

idよりもNSObject*またはid<NSObject>を優先的に使用することがよくあります。これは、少なくとも返されるオブジェクトがCocoaオブジェクトであることを確認するため、retain/release/autoreleaseなどのメソッドをそれ。

19
Peter N Lewis

メソッドの戻り型がidの場合、Objective-Cオブジェクトを返すことができます。

voidは、メソッドが何も返さないことを意味します。

void *は単なるポインタです。ポインターが指すアドレスのコンテンツを編集することはできません。

8
fphilipe

idは、Objective-Cオブジェクトへのポインターです。 void *anythingへのポインターです。 idの代わりにvoid *を使用することもできますが、何もコンパイラの警告が表示されないため、お勧めしません。

stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject および nixjunkie.blogspot.com/ 2008/03/id-vs-nsobject-vs-id.html

7
Michael
/// 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 Classオブジェクトとバインドできますが、void *は型なしポインターです。

4
jack

私の理解では、idはオブジェクトへのポインタを表しますが、void *は実際に何かを指すことができます。

2
hhafez

既に述べたことに加えて、コレクションに関連するオブジェクトとポインターには違いがあります。たとえば、NSArrayに何かを入れたい場合は、オブジェクト(「id」型)が必要で、そこに生データポインター(「void *」型)は使用できません。 [NSValue valueWithPointer:rawData]を使用して、void *rawDdataをコレクション内で使用するために「id」型に変換できます。一般に、「id」はより柔軟で、それに関連付けられたオブジェクトに関連するセマンティクスが多くなります。 idのObjective Cのタイプ を説明する他の例があります。

0
battlmonstr