Как узнать, включена ли в компиляторе поддержка ARC? - PullRequest
13 голосов
/ 27 февраля 2012

Мне нужно написать библиотеку в моем приложении для iOS.

Оператор должен быть предварительно обработан и определен как:

myObject ...

#if ARC
   // do nothing
#else
   [myObject release]
#endif

или процесс во время выполнения как:

if (ARC) {
   // do nothing
} else {
   [myObject release];
}

Как мне это сделать?

Пожалуйста, помогите мне! Спасибо.

Ответы [ 3 ]

28 голосов
/ 27 февраля 2012

Вы можете использовать __has_feature, вот так:

#if __has_feature(objc_arc)
// ARC is On
#else
// ARC is Off
#endif

Если вы также хотите собрать с GCC (Apple GCC не поддерживает ARC), вам также может понадобиться следующее для определения компилятора:

#if defined(__clang)
// It's Clang
#else
// It's 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 с.

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

Обратите внимание, что здесь есть дополнительные проверки, чтобы продемонстрировать, как можно (и нужно) избегать определения зарезервированных идентификаторов (на основе разговора в комментариях). Это не исчерпывающая, а демонстрация. Если вы часто пишете условные __has_feature проверки, вы можете определить новый макрос для этого, чтобы уменьшить и упростить определения.

9 голосов
/ 27 февраля 2012

Вы можете сделать это, используя макросы:

#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/; но я вставил его, чтобы убедиться, что он не потерян.

2 голосов
/ 27 февраля 2012

Как правило, вы не хотите делать такие вещи:

#if ARC
   // do nothing
#else
   [myObject release]
#endif

Поскольку это рецепт катастрофы, в таком коде скрывается множество тонких ошибок.Но если у вас есть вменяемый вариант для этого, возможно, вам лучше использовать макрос (я не знал __has_feature, спасибо, Джастин!):

#if __has_feature(objc_arc)
    #define MY_RELEASE(x) while (0) {}
#else
    #define MY_RELEASE(x) [x release]
#endif

Но я был бы весьманервный использовать даже это, потенциал боли огромен:)

...