Цель-C: разница между id и void *

В чем разница между id а также void *?

7 ответов

Решение

void * означает "ссылка на некоторый случайный фрагмент памяти с нетипизированным / неизвестным содержимым"

id означает "ссылка на некоторый случайный объект Objective-C неизвестного класса"

Есть дополнительные семантические различия:

  • В режимах GC Only или GC Supported компилятор будет создавать барьеры записи для ссылок типа id, но не для типа void *, При объявлении структур это может быть критической разницей. Объявление iVars как void *_superPrivateDoNotTouch; приведет к преждевременному пожатию объектов, если _superPrivateDoNotTouch на самом деле объект. Не делай этого.

  • пытаясь вызвать метод по ссылке void * type сожжет предупреждение компилятора.

  • пытаясь вызвать метод на 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 аргумент метода через как context аргумент. Это непрозрачный кусок данных размером с указатель, что касается NSArray, и вы можете использовать его для любых целей.

Без функции типа замыкания в языке это единственный способ перенести часть данных с функцией. Пример; если бы вы хотели, чтобы mySortFunc() выполняла условную сортировку как чувствительную к регистру или нечувствительную к регистру, так и сохраняя при этом многопоточность, вы бы пропустили индикатор чувствительности к регистру в контексте, что, вероятно, приводит к входу и выходу.

Хрупкие и подверженные ошибкам, но единственный способ.

Блоки решают эту проблему - блоки являются замыканиями для C. Они доступны в Clang - http://llvm.org/ и распространены в Snow Leopard ( http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).

id - это указатель на целевой объект C, где void* - указатель на что-либо.

id также отключает предупреждения, связанные с вызовом неизвестных mthods, например:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

не даст обычного предупреждения о неизвестных методах. Это, конечно, вызовет исключение во время выполнения, если obj не равен nil или действительно не реализует этот метод.

Часто вы должны использовать NSObject* или же id<NSObject> в предпочтении id, что по крайней мере подтверждает, что возвращаемый объект является объектом Какао, так что вы можете безопасно использовать такие методы, как retain/release/autorelease.

id указатель на объект Objective-C void * это указатель на что-нибудь. Вы могли бы использовать void * вместо id, но это не рекомендуется, потому что вы никогда не получите предупреждения компилятора ни за что.

Вы можете захотеть увидеть /questions/31148599/v-chem-raznitsa-mezhdu-obyavleniem-peremennoj-id-i-nsobject и http://unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html.

Если метод имеет возвращаемый тип id Вы можете вернуть любой объект Objective-C.

void значит, метод ничего не вернет.

void * это просто указатель. Вы не сможете редактировать содержимое по адресу, на который указывает указатель.

/// 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;

Приведенный выше код взят из objc.h, поэтому похоже, что id является экземпляром структуры objc_object, и указатель is a может связываться с любым объектом класса Objective C, а void* - просто нетипизированный указатель.

Насколько я понимаю, id представляет собой указатель на объект, в то время как void * может указывать на что-либо на самом деле, при условии, что вы приведете его к типу, который хотите использовать как

В дополнение к тому, что уже сказано, есть различие между объектами и указателями, связанными с коллекциями. Например, если вы хотите поместить что-то в NSArray, вам нужен объект (типа "id"), и вы не можете использовать там указатель необработанных данных (типа "void *"). Ты можешь использовать [NSValue valueWithPointer:rawData] преобразовать void *rawDdata к типу "ID" для использования его внутри коллекции. В общем, "id" более гибок и имеет больше семантики, связанной с объектами, прикрепленными к нему. Есть больше примеров, объясняющих тип идентификатора Objective C здесь.

Другие вопросы по тегам