Когда использовать UIKIT_EXTERN или только extern

Я предполагаю, что я использовал бы только UIKIT_EXTERN, если в моем проекте есть вероятность использования кода на С++, который может использовать переменную.

Если это так, не было бы безопасно объявлять все ваши внешние константы с помощью UIKIT_EXTERN?

Почему я не вижу этого больше?

Ответ 1

Я предполагаю, что я использовал бы только UIKIT_EXTERN, если в моем проекте есть вероятность использования кода на С++, который может использовать переменную.

Right. Это основная причина. Это происходит потому, что символы C и С++ используют разные соглашения об именах.

Существует менее распространенная причина: UIKIT_EXTERN также определяет видимость по умолчанию.

Примечание. В общем случае "символ" - не "переменная", поскольку extern также может применяться к константам, функциям и т.д.

Если это так, не было бы безопасно объявлять все ваши внешние константы с помощью UIKIT_EXTERN?

Короткий ответ. Для использования этой формы было бы хорошей практикой (читайте: "безопасно" ), но обычно лучше всего, чтобы ваша библиотека объявила свой собственный эквивалент UIKIT_EXTERN.


UIKIT_EXTERN - это декларация UIKit. Библиотеки не должны зависеть от этого объявления и просто определять свой собственный синоним - и многие это делают, но я нахожу его более распространенным в C и С++, потому что эти программы часто нацелены на большее количество платформ и хороший процент Программы iOS не разработаны для поддержки других платформ. В противном случае программы Objective-C, которые не требуют UIKit, могут зависеть от UIKit из-за этого объявления, поэтому им придется импортировать UIKit (так что объявление UIKIT_EXTERN видно).

Кроме того, UIKit недоступен на всех платформах, где могут выполняться программы iOS (т.е. это может быть C, С++ или зависит от Foundation и переносится на OS X). Поэтому даже если кто-то (любопытно) настаивал на том, чтобы объявить свои собственные, было плохой идеей, выбор CF_EXPORT (эквивалент CoreFoundation) был бы более переносимым вариантом, поскольку он также мог использоваться для C, С++ и OS X. Кроме того, ваша библиотека необходимо было бы включить CoreFoundation (как минимум).

Если ваша библиотека зависит от UIKit, и инфраструктура должна быть импортирована вашей библиотекой, то маловероятно, что использование их синонима вызовет проблему для вашей библиотеки.

Но это довольно большой набор условий - очень легко для вашей библиотеки просто объявить свой собственный. Короче говоря, хорошо написанная и переносимая библиотека должна (почти) никогда не использовать "raw" extern, и не должно быть ненужных зависимостей библиотек - это хорошо (UIKit в этом случае).

Было бы плохой выбор дизайна для использования UIKIT_EXTERN, если ваша библиотека не была неотделима от UIKit - например, коллекция подклассов UIView.

Если ваша библиотека просто использует типы Foundation, тогда импорт UIKit означает, что ваша библиотека будет (излишне) непригодной для использования в OS X (пока этот импорт UIKit не будет удален).

Люди, которые не имеют большого опыта использования С++ с C (включая надмножества), могут не знать, что имена символов различны, поэтому они могут просто использовать extern напрямую. Наконец, некоторые программы изначально не предназначались для использования вне трансляций C и/или Objective-C, поэтому они могли просто использовать extern без условного декодирования для перевода.

Наконец, UIKIT_EXTERN может не делать то, что вы ожидаете/хотите, поскольку оно указывает:

  • символ внешнего символа
  • который имеет видимость по умолчанию

Для символов библиотеки, видимых для трансляций ObjC, это идеально.

Ответ 2

Это прежде всего сделать класс видимым вне текущей библиотеки/исполняемого файла. Вероятно, вам не понадобится использовать его, если вы не разрабатываете библиотеки.

Как вы отмечаете, основное преимущество использования макроса заключается в том, что он создает дополнительную защиту С++ extern, поэтому, если вы действительно разрабатываете библиотеку, это определенно хорошая идея (в противном случае вызывающий должен быть и добавьте объявление extern C).

Это описано в документации ADC:

и здесь достаточно хорошо ответил: