Objective-C: różnica między ID i void *

Jaka jest różnica między id a void *?

Author: mk12, 2009-08-20

7 answers

void * oznacza "odniesienie do jakiegoś przypadkowego fragmentu pamięci z nieopisaną / nieznaną zawartością" [21]}

id oznacza "odniesienie do jakiegoś losowego obiektu-C nieznanej klasy"

Istnieją dodatkowe różnice semantyczne:

  • W trybie tylko GC lub obsługiwanym przez GC kompilator będzie emitował bariery zapisu dla referencji typu id, ale nie dla typu void *. Podczas deklarowania struktur może to być krytyczna różnica. Deklarowanie ivarów jak void *_superPrivateDoNotTouch; będzie powoduje przedwczesne zbieranie obiektów, jeśli {[7] } jest rzeczywiście obiektem. Nie rób tego.

  • Próba wywołania metody na referencji typu void * spowoduje wyświetlenie ostrzeżenia kompilatora.

  • Próba wywołania metody na typie id będzie ostrzegać tylko wtedy, gdy wywołana metoda nie została zadeklarowana w żadnej z deklaracji @interface widzianych przez kompilator.

Tak więc, nigdy nie należy odnosić się do obiektu jako void *. Podobnie należy unikać użycie zmiennej typu id do odniesienia się do obiektu. Użyj najbardziej specyficznego odniesienia do klasy, które możesz wpisać. Nawet NSObject * jest lepsze niż id, ponieważ kompilator może przynajmniej zapewnić lepszą walidację wywołań metody względem tego odniesienia.

Jedynym powszechnym i prawidłowym użyciem void * jest nieprzezroczyste odniesienie do danych, które jest przekazywane przez inne API.

Rozważmy metodę sortedArrayUsingFunction: context: z NSArray:

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

Funkcja sortowania zostanie zadeklarowana as:

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

W tym przypadku NSArray przekazuje tylko to, co przekazujesz jako argument context do metody through jako argument context. Jest to nieprzezroczysty kawałek danych o rozmiarze wskaźnika, jeśli chodzi o NSArray, i możesz go używać w dowolnym celu.

BEZ funkcji typu zamknięcia w języku, jest to jedyny sposób na przenoszenie kawałka danych za pomocą funkcji. Przykład; jeśli chcesz, aby funkcja mySortFunc() warunkowo sortowała wielkość liter lub niewrażliwe na wielkość liter, będąc jednocześnie bezpiecznym dla wątków, można przekazać wskaźnik is-case-sensitive w kontekście, prawdopodobnie rzucając się na drogę wejścia i wyjścia.

Kruche i podatne na błędy, ale jedyne wyjście.

Bloki rozwiązują to -- bloki są zamknięciami dla C. są dostępne w Clang -- http://llvm.org / i są wszechobecne w Snow Leopardzie (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).

 233
Author: bbum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-09 10:12:45

Id jest wskaźnikiem do obiektu objective C, gdzie jako void* jest wskaźnikiem do czegokolwiek.

Id wyłącza również ostrzeżenia związane z wywołaniem nieznanych mthods, więc na przykład:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

Nie da zwykłego ostrzeżenia o nieznanych metodach. Spowoduje to oczywiście wywołanie wyjątku w czasie wykonywania, chyba że obj jest zerowy lub naprawdę zaimplementuje tę metodę.

Często powinieneś użyć NSObject* lub id<NSObject> zamiast id, co przynajmniej potwierdza, że zwracany obiekt jest Obiekt Cocoa, dzięki czemu można bezpiecznie używać na nim metod takich jak retain/release/autorelease.

 19
Author: Peter N Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-14 19:56:41

Jeśli metoda ma zwracany typ id, możesz zwrócić dowolny obiekt Objective-C.

void oznacza to, że metoda niczego nie zwróci.

void * to tylko wskazówka. Nie będzie można edytować zawartości pod adresem, na który wskazuje wskaźnik.

 8
Author: fphilipe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 05:53:00

id jest wskaźnikiem do obiektu Objective-C. void * jest wskaźnikiem do czegokolwiek . Możesz użyć void * zamiast id, ale nie jest to zalecane, ponieważ nigdy nie otrzymasz ostrzeżeń kompilatora dla czegokolwiek.

You may want to see stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject i unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html .

 7
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:54
/// 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;

Powyższy kod pochodzi z objc.h, wygląda więc na to, że id jest instancją struktury objc_object, a wskaźnik isa może wiązać się z dowolnym obiektem klasy Objective C, podczas gdy void* jest tylko nietypowanym wskaźnikiem.

 4
Author: jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-19 09:21:52

Rozumiem, że id reprezentuje wskaźnik do obiektu, podczas gdy void * może wskazywać na cokolwiek naprawdę, o ile następnie rzucisz go na typ, do którego chcesz go użyć

 2
Author: hhafez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 05:54:09

Oprócz tego, co już zostało powiedziane, Istnieje różnica między obiektami a wskaźnikami związanymi ze zbiorami. Na przykład, jeśli chcesz umieścić coś w NSArray, potrzebujesz obiektu (typu "id") i nie możesz używać tam wskaźnika surowych danych (typu " void *"). Możesz użyć [NSValue valueWithPointer:rawData], Aby przekonwertować void *rawDdata na typ "id", aby użyć go wewnątrz kolekcji. Ogólnie " id " jest bardziej elastyczny i ma więcej semantyki związanej z dołączonymi do niego obiektami. Jest więcej przykładów wyjaśniających Typ id Objective C here .

 0
Author: battlmonstr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-30 06:57:42