简体   繁体   中英

Xcode preprocessor macro to check if Base SDK >= iOS 7.0

Is there any preprocessor macro to compile certain parts of code only if the Base SDK is 7.0 or higher? The "__IPHONE_7_0" defined constant seems to be linked to the iOS development target (and not to the base SDK).

I am using XCode 5 with iOS 7 and iOS 6.1 installed.

The reason why I am asking this is that I am currently transitioning an app from iOS 6 to iOS 7. There are quite a few things to adjust, and I would currently still like to compile my app with the iOS 6.1 as base SDK (and with development target iOS 6.0), but would already like to add some code that I will want for whenever I compile with iOS 7 SDK, but which does not compile if base SDK is iOS 6.1.

Example:

if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
    [_tableView setSeparatorInset:UIEdgeInsetsZero];
}

This above piece of code does not compile with iOS 6.1 base SDK, as it complains about setSeparatorInset not being defined for UITableView. Hence I would like to include this piece of code inside a preprocessor directive, conditionally on the base SDK.

You should read Apple's SDK Compatibility Guide where all those techniques are explained.

In particular, they recommend to use the __IPHONE_OS_VERSION_MIN_REQUIRED macro to test against the Deployment Target of your project (minimum supported version), and for your case use the __IPHONE_OS_VERSION_MAX_ALLOWED macro to test the Base SDK used for compilation .


Example:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
// Only COMPILE this if compiled against BaseSDK iOS7.0 or greater
if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
   // Even when compiled with BaseSDK 7, only EXECUTE that if the user uses an
   // OS that support this method (namely if the user is running iOS7 or later,
   // but not for users running iOS6).
   [_tableView setSeparatorInset:UIEdgeInsetsZero];
}
#endif

Important note: You should use numeric constants in your comparison as if you test #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0 for example it won't work when using SDK 6, as __IPHONE_7_0 is not defined thus evaluated to 0 in that context and your condition won't work as expected.

Yes you can use the __IPHONE_7_0 define:

#ifdef __IPHONE_7_0
    if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [_tableView setSeparatorInset:UIEdgeInsetsZero];
    }
#endif

As per Apple Doc you should use NSFoundationVersionNumber to distinguish between iOS 7 and others. You can make it simpler using following macros:

#define isIOS6 floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1 
#define isIOS7 floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1

and then later in code do

#ifdef __IPHONE_7_0
    if (isIOS7) {
       // Do additional stuff for iOS 7.
    } 
#endif

Yes you should check on both compile-time (with #ifdef ) and run-time (with isIOS7 ) this way you will be able to compile with iOS6 SDK , iOS7 SDK, and also iOS7 SDK with an iOS6 target.

OH! Remember that you cannot do if (!isIOS7) you have to use if (isIOS6) .

https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/

Also, you can use this macro

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending)

eg if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.1")) {[self doSomething];} else {[self doSomethingElse];}

You shouldn't test for the sdk but for availability of the method / class IMHO. So not with a precompiled at all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM