Objective-C: differenza tra id e void *
-
19-09-2019 - |
Domanda
Qual è la differenza tra id
e void *
?
Soluzione
void *
significa "un riferimento a qualche pezzo casuale o' memoria con / contenuti sconosciuti senza tipo"
id
significa "un riferimento a un oggetto Objective-C casuale di classe sconosciuta"
Ci sono ulteriori differenze semantiche:
-
Sotto GC Solo o modalità GC supportati, il compilatore emetterà barriere di scrittura per i riferimenti di tipo
id
, ma non per il tipovoid *
. Quando si dichiara strutture, questa può essere una differenza critica. ivars dichiarano comevoid *_superPrivateDoNotTouch;
causeranno mietitura prematura degli oggetti se_superPrivateDoNotTouch
è in realtà un oggetto. Non farlo. -
tentativo di invocare un metodo su un riferimento di tipo
void *
sarà barf un avviso del compilatore. -
tentativo di invocare un metodo su un tipo di
id
avvertirà solo se il metodo di essere chiamato non è stato dichiarato in nessuna delle dichiarazioni@interface
visti dal compilatore.
In questo modo, non si dovrebbe mai fare riferimento a un oggetto come void *
. Analogamente, si dovrebbe evitare di utilizzare una variabile id
tipizzato per fare riferimento a un oggetto. Utilizzare il più specifico riferimento digitato classe che si può. Ancora NSObject *
è meglio che id
perché il compilatore può, almeno, fornire una migliore convalida dei metodi invocazioni contro quel riferimento.
L'unico uso comune e valido void *
è come riferimento dati opaco che viene fatto passare attraverso un altro API.
Si consideri il metodo sortedArrayUsingFunction: context:
di NSArray
:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
La funzione di ordinamento sarebbe stata dichiarata come:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
In questo caso, il NSArray semplicemente passa tutto ciò si passa come argomento context
al metodo attraverso come argomento context
. Si tratta di un pezzo opaca dei dati di dimensioni puntatore, per quanto NSArray è interessato, e si è liberi di usarlo per qualsiasi scopo che si desidera.
Senza Funzione chiusure nella lingua, questo è l'unico modo per portare con sé un pezzo di dati con una funzione. Esempio; se si voleva mySortFunc () per condizionalmente sorta come maiuscole e minuscole o maiuscole e minuscole, mentre però ancora in fase di thread-safe, si dovrebbe passare l'indicatore sensibile è minuscole nel contesto, probabilmente colata sul modo in e via d'uscita.
Fragile e soggetto a errori, ma l'unico modo.
Blocchi risolvono questo - I blocchi sono chiusure per C. Sono disponibili in Clang - http://llvm.org/ e sono molto diffusi in Snow Leopard ( http: / /developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf ).
Altri suggerimenti
id è un puntatore ad un oggetto C oggettiva, dove, come void * è un puntatore a nulla.
id si spegne anche avvisi relativi a chiamare mthods sconosciuti, così per esempio:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
non darà il solito avvertimento sui metodi sconosciuti. Sarà, naturalmente, solleva un'eccezione in fase di esecuzione, a meno obj è nullo o realmente non attuare tale metodo.
Spesso si consiglia di utilizzare NSObject*
o id<NSObject>
a preferenza di id
, che almeno conferma che l'oggetto restituito è un oggetto di cacao, in modo da poter tranquillamente utilizzare metodi come mantenere / release / autorelease su di esso.
Se un metodo ha un tipo di ritorno di id
è possibile restituire qualsiasi oggetto Objective-C.
void
significa, il metodo non restituisce nulla.
void *
è solo un puntatore. Non sarà in grado di modificare il contenuto sull'indirizzo il puntatore punta a.
id
è un puntatore ad un oggetto Objective-C. void *
è un puntatore a niente . Si potrebbe utilizzare void *
invece di id
, ma non è consigliabile perché si sarebbe mai ottenere gli avvisi del compilatore per qualsiasi cosa.
Si consiglia di vedere stackoverflow.com/ domande / 466.777 / cosa-la-differenza-tra-dichiarazione-a-variabile id-e-NSObject e 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;
Il codice di cui sopra è da objc.h, così sembra che id è un esempio di objc_object puntatore struct e ISA può legarsi con qualsiasi oggetto Objective C Class, mentre void * è solo un puntatore non tipizzato.
La mia comprensione è che id rappresenta un puntatore ad un oggetto mentre void * può puntare a qualcosa di veramente, fino a quando si poi gettato al tipo che si desidera utilizzare come
In aggiunta a ciò che è già detto, c'è una differenza tra oggetti e puntatori relativi alle collezioni. Ad esempio, se si vuole mettere qualcosa in NSArray, è necessario un oggetto (di tipo "id"), e non è possibile utilizzare un puntatore dati grezzi lì (di tipo "void *"). È possibile utilizzare per convertire [NSValue valueWithPointer:rawData]
void *rawDdata
al tipo di "id" per il suo utilizzo all'interno di una collezione. In generale "id" è più flessibile e ha più semantica relativi agli oggetti collegati ad esso. Ci sono altri esempi che spiegano tipo id di Objective C qui .