如何知道编译器是否启用了ARC支持?
我需要在我的iOS应用程序中编写一个库。
该声明应该被预处理定义为:
myObject ... #if ARC // do nothing #else [myObject release] #endif
或运行时过程如下:
if (ARC) { // do nothing } else { [myObject release]; }
我能怎么做?
请帮帮我! 谢谢。
你可以使用__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
更新
结合起来,他们将采取一般forms:
#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
。
如果你使用的编译器增加了支持,你将不得不为此添加一个case(在这种情况下,编译器错误可能会捕获错误,因为它可能会禁止使用ref count操作)。
请注意,这有额外的检查来演示如何可以(也应该)避免定义保留标识符(基于评论中的对话)。 这不是详尽的,而是一个示范。 如果您经常发现自己正在编写条件__has_feature
检查,则可能需要为此定义一个新的macros以减less和简化定义。
你可以使用macros来做到这一点:
#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/ ; 但我粘贴它,以确保它不会丢失。
你通常不想做这样的事情:
#if ARC // do nothing #else [myObject release] #endif
因为这是一个灾难的秘诀,潜伏在这样的代码中有许多微妙的错误。 但是,如果你有一个明智的用例,那么你也许会用macros观来更好(我不知道__has_feature
,谢谢Justin!):
#if __has_feature(objc_arc) #define MY_RELEASE(x) while (0) {} #else #define MY_RELEASE(x) [x release] #endif
但即使如此,我也会很紧张,痛苦的潜力是巨大的:)