А хороший разработчик должен знать больше, чем, как кодировать
void *
означает "ссылка на некоторый случайный кусок памяти с нетипизированным / неизвестным содержимым »
id
означает« ссылку на некоторый случайный объект Objective-C неизвестного класса »
Есть дополнительные семантические различия:
Только в GC или В режимах, поддерживаемых сборщиком мусора, компилятор создает барьеры для записи для ссылок типа id
, но не для типа void *
. При объявлении структур это может быть критическим отличием. Объявление iVars типа void * _superPrivateDoNotTouch;
вызовет преждевременное пожатие объектов, если _superPrivateDoNotTouch
на самом деле является объектом. Не делай этого.
попытка вызвать метод для ссылки типа void *
вызовет предупреждение компилятора.
попытка вызвать метод для типа id
выдаст предупреждение, только если вызываемый метод не был объявлен ни в одном из объявлений @interface
, видимых компилятором.
Таким образом, нельзя ссылаться на объект как на void *
. Точно так же следует избегать использования типизированной переменной id
для ссылки на объект. Используйте наиболее конкретную ссылку, типизированную для класса, которую вы можете. Даже NSObject *
лучше, чем id
, потому что компилятор может, по крайней мере, обеспечить лучшую проверку вызовов методов по этой ссылке.
Единственное распространенное и допустимое использование void *
- это непрозрачная ссылка на данные, которая передается через некоторый другой API.
Рассмотрим метод sortedArrayUsingFunction: context:
для NSArray
:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
Функция сортировки будет объявлена как:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
В этом случае NSArray просто передает все, что вы передаете, как аргумент context
в метод как аргумент контекста
. Что касается NSArray, это непрозрачный кусок данных размером с указатель, и вы можете использовать его для любых целей.
Без функции типа закрытия в языке это единственный способ сохранить кусок данных с функцией. Пример; если вы хотите, чтобы mySortFunc () выполняла условную сортировку с учетом регистра или без учета регистра, но при этом оставалась поточно-ориентированной,
id - указатель на объект C, где void * - указатель на что угодно.
id также отключает предупреждения, связанные с вызовом неизвестных методов, например:
[(id) obj doSomethingWeirdYouveNeverHeardOf];
не будет выдавать обычное предупреждение о неизвестных методах. Конечно, это вызовет исключение во время выполнения, если obj не равен nil или действительно не реализует этот метод.
Часто вы должны использовать NSObject *
или id
в предпочтение id
, что, по крайней мере, подтверждает, что возвращенный объект является объектом Какао, поэтому вы можете безопасно использовать для него такие методы, как keep / release / autorelease.
Если метод имеет тип возврата id
вы можете вернуть любой объект Objective-C.
void
означает, что метод ничего не вернет.
void *
- это просто указатель. Вы не сможете редактировать содержимое адреса, на который указывает указатель.
id
- указатель на объект Objective-C. void *
- указатель на что-либо . Вы можете использовать void *
вместо id
, но это не рекомендуется, потому что вы никогда не получите предупреждений компилятора ни о чем.
Возможно, вы захотите увидеть stackoverflow.com / questions / 466777 / что-разница-между-объявлением-идентификатора-переменной-и-nsobject и unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id .html .
Насколько я понимаю, id представляет собой указатель на объект, а void * может указывать на что угодно, если вы затем приведете его к типу, который хотите использовать как