Как узнать, включен ли в компилятор ARC-поддержка?
Мне нужно написать lib в моем приложении iOS.
Утверждение должно быть определено как:
myObject ...
#if ARC
// do nothing
#else
[myObject release]
#endif
или процесс выполнения как:
if (ARC) {
// do nothing
} else {
[myObject release];
}
Как я могу это сделать?
Пожалуйста, помогите мне! Спасибо.
Ответы
Ответ 1
Вы можете использовать __has_feature
, например:
#if __has_feature(objc_arc)
// ARC is On
#else
// ARC is Off
#endif
Если вы хотите также построить с помощью GCC (Apple GCC не поддерживает ARC), для определения компилятора может понадобиться следующее:
#if defined(__clang)
// It Clang
#else
// It GCC
#endif
Обновление
Комбинированные, они будут иметь общий вид:
#if defined(__clang)
#if !defined(__has_feature)
// idk when clang introduced this
#error This version of clang does not support __has_feature
#endif
#define MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION __has_feature(objc_arc)
#else
// for every compiler other than clang:
#if defined(__has_feature)
#error Another compiler supports __has_feature
#endif
#define MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION 0
#endif
Затем просто используйте MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION
в своих источниках или для дальнейшего #define
s.
Если вы используете компилятор, добавляете поддержку, вам придется добавить к нему случай (и ошибки компилятора, скорее всего, поймут ошибку в этом случае, так как это, скорее всего, запретит использование ref count ops).
Обратите внимание, что у этого есть дополнительные проверки, чтобы продемонстрировать, как можно (и должно) избегать определения зарезервированных идентификаторов (на основе беседы в комментариях). Это не исчерпывающий, а демонстрационный. Если вы обнаружите, что часто выполняете проверку условных __has_feature
проверок, вы можете определить новый макрос для этого, чтобы уменьшить и упростить определения.
Ответ 2
Вы можете сделать это с помощью макросов:
#if !defined(__clang__) || __clang_major__ < 3
#ifndef __bridge
#define __bridge
#endif
#ifndef __bridge_retain
#define __bridge_retain
#endif
#ifndef __bridge_retained
#define __bridge_retained
#endif
#ifndef __autoreleasing
#define __autoreleasing
#endif
#ifndef __strong
#define __strong
#endif
#ifndef __unsafe_unretained
#define __unsafe_unretained
#endif
#ifndef __weak
#define __weak
#endif
#endif
#if __has_feature(objc_arc)
#define SAFE_ARC_PROP_RETAIN strong
#define SAFE_ARC_RETAIN(x) (x)
#define SAFE_ARC_RELEASE(x)
#define SAFE_ARC_AUTORELEASE(x) (x)
#define SAFE_ARC_BLOCK_COPY(x) (x)
#define SAFE_ARC_BLOCK_RELEASE(x)
#define SAFE_ARC_SUPER_DEALLOC()
#define SAFE_ARC_AUTORELEASE_POOL_START() @autoreleasepool {
#define SAFE_ARC_AUTORELEASE_POOL_END() }
#else
#define SAFE_ARC_PROP_RETAIN retain
#define SAFE_ARC_RETAIN(x) ([(x) retain])
#define SAFE_ARC_RELEASE(x) ([(x) release])
#define SAFE_ARC_AUTORELEASE(x) ([(x) autorelease])
#define SAFE_ARC_BLOCK_COPY(x) (Block_copy(x))
#define SAFE_ARC_BLOCK_RELEASE(x) (Block_release(x))
#define SAFE_ARC_SUPER_DEALLOC() ([super dealloc])
#define SAFE_ARC_AUTORELEASE_POOL_START() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#define SAFE_ARC_AUTORELEASE_POOL_END() [pool release];
#endif
Вышеизложенное произошло с сайта: http://raptureinvenice.com/arc-support-without-branches/; но я вставил его, чтобы он не потерялся.
Ответ 3
Обычно вы не хотите делать такие вещи:
#if ARC
// do nothing
#else
[myObject release]
#endif
Поскольку его рецепт катастрофы, в этом коде есть много тонких ошибок. Но если у вас есть разумный прецедент для этого, возможно, вам будет лучше с макросом (я не знал __has_feature
, спасибо Justin!):
#if __has_feature(objc_arc)
#define MY_RELEASE(x) while (0) {}
#else
#define MY_RELEASE(x) [x release]
#endif
Но я бы очень нервничал, чтобы использовать даже это, потенциал боли огромен:)