Objective-C: diferencia entre la ID y void *
-
19-09-2019 - |
Pregunta
¿Cuál es la diferencia entre id
y void *
?
Solución
void *
significa "una referencia a algún trozo aleatorio o' memoria con desconocidos / contenidos sin tipo"
id
significa "una referencia a algunos Objective-C objeto aleatoria de clase desconocida"
Existen diferencias semánticas adicionales:
-
En sólo GC o GC modos soportados, el compilador emitirá barreras de escritura para las referencias de tipo
id
, pero no para el tipovoid *
. Al declarar estructuras, esto puede ser una diferencia crítica. Declarando Ivars comovoid *_superPrivateDoNotTouch;
causarán cosecha prematura de objetos si_superPrivateDoNotTouch
es en realidad un objeto. No hagas eso. -
intentar invocar un método en una referencia de tipo
void *
va a vomitar una advertencia del compilador. -
intentar invocar un método en un tipo de
id
solamente un aviso cuando el método se llama no se ha declarado en cualquiera de las declaraciones@interface
visto por el compilador.
Por lo tanto, uno nunca debe referirse a un objeto como un void *
. Del mismo modo, se debe evitar el uso de una variable de id
escrito para referirse a un objeto. Utilice la referencia mecanografiado clase más específica que pueda. Incluso es mejor que NSObject *
id
porque el compilador puede, al menos, ofrecer una mejor validación de invocaciones de métodos contra esa referencia.
El uso común y válida de void *
es como una referencia de datos opaco que se pasa a través de alguna otra API.
Considere el método de sortedArrayUsingFunction: context:
NSArray
:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
La función de clasificación sería declarado como:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
En este caso, el NSArray simplemente pasa lo que pasa en context
como argumento al método a través context
como argumento. Es un trozo opaca de datos de tamaño de puntero, en lo que se refiere a NSArray, y usted es libre de usarlo para cualquier propósito que desee.
Sin Lugar del tipo de cierre en la lengua, esta es la única manera de llevar a lo largo de un trozo de datos con una función. Ejemplo; si quería mySortFunc () para condicionalmente especie como entre mayúsculas y minúsculas o mayúsculas o minúsculas, y al mismo tiempo dejar de ser seguro para subprocesos, usted pasaría el indicador está entre mayúsculas y minúsculas en el contexto, es probable fundición en el camino de entrada y salida.
frágil y propenso a errores, pero la única manera.
Bloques resuelven este - bloques son cierres para C. Están disponibles en Clang - http://llvm.org/ y son omnipresentes en Snow Leopard ( http: / /developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf ).
Otros consejos
id es un puntero a un objeto objetivo C, donde como void * es un puntero a nada.
Identificación del también desactiva las advertencias relacionadas con llamar mthods desconocidos, así por ejemplo:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
no dar la advertencia habitual acerca de los métodos desconocidos. Será, por supuesto, provoca una excepción en tiempo de ejecución a menos obj es nula o muy no aplicar ese método.
A menudo se debe utilizar NSObject*
o id<NSObject>
con preferencia a id
, que al menos confirma que el objeto devuelto es un objeto de cacao, para que pueda utilizar con seguridad métodos como retener / liberar / autorelease en él.
Si un método tiene un tipo de retorno de id
puede devolver cualquier objeto de Objective-C.
significa void
, el método no devuelve nada.
void *
es sólo un puntero. Usted no será capaz de editar el contenido de la dirección de los puntos de puntero a.
id
es un puntero a un objeto Objetivo-C. void *
es un puntero a lo . Se podría utilizar en lugar de void *
id
, pero no es recomendable porque nunca se obtendría advertencias del compilador para nada.
Es posible que desee ver stackoverflow.com/ preguntas / 466777 / cuál es-la-diferencia-entre-declara-a-variable-id-y-NSObject y unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html .
/// 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;
El código anterior es de objc.h, por lo que parece que la identificación es una instancia de puntero de estructura e ISA objc_object puede unirse con cualquier objeto Clase C Objetivo, mientras que void * es sólo un puntero sin tipo.
Mi entendimiento es que Identificación representa un puntero a un objeto mientras void * puede apuntar a cualquier cosa en realidad, todo el tiempo que a continuación, lanzas con el tipo que desea utilizar como
Además de lo que ya se dijo, hay una diferencia entre los objetos y punteros relacionados con colecciones. Por ejemplo, si quieres poner algo en NSArray, necesita un objeto (de tipo "id"), y no se puede utilizar un puntero de datos en bruto que hay (de tipo "void *"). Se puede utilizar para convertir [NSValue valueWithPointer:rawData]
void *rawDdata
al tipo "id" para usarlo dentro de una colección. En "id" en general es más flexible y tiene más semántica relacionados con los objetos unidos a él. Hay más ejemplos que explican Tipo de Identificación de Objective C aquí.