168 votes

Objective-C : différence entre id et void *

Quelle est la différence entre id et void * ?

235voto

bbum Points 124887

void * signifie "une référence à une partie aléatoire de la mémoire avec un contenu inconnu".

id signifie "une référence à un objet Objective-C aléatoire de classe inconnue".

Il existe des différences sémantiques supplémentaires :

  • Dans les modes GC Only ou GC Supported, le compilateur émettra des barrières d'écriture pour les références de type id mais pas pour le type void * . Lors de la déclaration de structures, cette différence peut s'avérer cruciale. Déclarer des iVars comme void *_superPrivateDoNotTouch; entraînera une récolte prématurée d'objets si _superPrivateDoNotTouch est en fait un objet. Ne faites pas ça.

  • en essayant d'invoquer une méthode sur une référence de void * fera apparaître un avertissement du compilateur.

  • en tentant d'invoquer une méthode sur un id n'émettra un avertissement que si la méthode appelée n'a pas été déclarée dans l'une des catégories de l'annexe 1. @interface déclarations vues par le compilateur.

Ainsi, il ne faut jamais faire référence à un objet en tant que void * . De même, il faut éviter d'utiliser un id variable typée pour faire référence à un objet. Utilisez la référence typée classe la plus spécifique possible. Même NSObject * est meilleur que id car le compilateur peut, au moins, fournir une meilleure validation des invocations de méthodes par rapport à cette référence.

La seule utilisation commune et valide de void * est une référence de données opaque qui est transmise par une autre API.

Considérez le sortedArrayUsingFunction: context: méthode de NSArray :

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

La fonction de tri serait déclarée comme :

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

Dans ce cas, la NSArray se contente de transmettre ce que vous passez en tant que context à la méthode par le biais de l'argument context argument. Il s'agit d'un morceau opaque de données de la taille d'un pointeur, dans la mesure où NSArray est concerné, et vous êtes libre de l'utiliser dans le but que vous souhaitez.

En l'absence d'une fonctionnalité de type fermeture dans le langage, c'est le seul moyen de transporter un gros morceau de données avec une fonction. Exemple : si vous vouliez que mySortFunc() trie conditionnellement en fonction de la casse ou de l'insensibilité à la casse, tout en étant sûr pour les threads, vous passeriez l'indicateur is-case-sensitive dans le contexte, en effectuant probablement un casting à l'entrée et à la sortie.

Fragile et sujet aux erreurs, mais la seule solution.

Les blocs résolvent ce problème -- Les blocs sont des fermetures pour C. Ils sont disponibles dans Clang --. http://llvm.org/ et sont omniprésents dans Snow Leopard ( http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf ).

19voto

Peter N Lewis Points 12025

Id est un pointeur vers un objet C objectif, alors que void* est un pointeur vers n'importe quoi.

id désactive également les avertissements liés à l'appel de méthodes inconnues, donc par exemple :

[(id)obj doSomethingWeirdYouveNeverHeardOf];

ne donnera pas l'avertissement habituel concernant les méthodes inconnues. Il lèvera, bien sûr, une exception au moment de l'exécution, à moins que obj ne soit nil ou qu'il implémente réellement cette méthode.

Vous devez souvent utiliser NSObject* ou id<NSObject> de préférence à id ce qui confirme au moins que l'objet retourné est un objet Cocoa, et que vous pouvez donc utiliser en toute sécurité des méthodes comme retain/release/autorelease.

8voto

Philipe Points 1838

Si une méthode a un type de retour de id vous pouvez retourner n'importe quel objet Objective-C.

void signifie que la méthode ne retournera rien.

void * n'est qu'un pointeur. Vous ne pourrez pas modifier le contenu de l'adresse vers laquelle pointe le pointeur.

7voto

Michael Points 1492

id est un pointeur vers un objet Objective-C. void * est un pointeur vers tout ce qui est . Vous pouvez utiliser void * au lieu de id mais ce n'est pas recommandé car vous n'obtiendrez jamais d'avertissements du compilateur pour quoi que ce soit.

Vous voudrez peut-être voir stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject et unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html .

2voto

hhafez Points 13240

Si j'ai bien compris, id représente un pointeur vers un objet, tandis que void * peut pointer vers n'importe quoi, du moment que vous le castez ensuite vers le type que vous voulez utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X