Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

xcode

ios

ios7

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.

like image 749
quentinadam Avatar asked Nov 05 '13 13:11

quentinadam


4 Answers

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.

like image 104
AliSoftware Avatar answered Nov 20 '22 13:11

AliSoftware


Yes you can use the __IPHONE_7_0 define:

#ifdef __IPHONE_7_0
    if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [_tableView setSeparatorInset:UIEdgeInsetsZero];
    }
#endif
like image 31
rckoenes Avatar answered Nov 20 '22 13:11

rckoenes


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/

like image 13
Mojtaba Avatar answered Nov 20 '22 13:11

Mojtaba


Also, you can use this macro

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

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

like image 3
Akki Avatar answered Nov 20 '22 13:11

Akki