36

I've got some code I want to only execute on the latest iPhone SDK (3.0), however I can't seem to figure out a way to target just 3.0 and ignore 2.2.1 etc. There is an ifdef statement, but it just seems to cover the entire iPhone:

#if TARGET_OS_IPHONE

Any help is appreciated.

Oliver
  • 1,279
  • 5
  • 14
  • 20

8 Answers8

88

You can use this #define to change what you build for each SDK...

#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_2_2
// iPhone 3.0 code here
#endif

And do this at run-time to run code for 3.0 and above:

float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 3.0)
    {
    // iPhone 3.0 code here
    }
Jane Sales
  • 13,526
  • 3
  • 52
  • 57
  • 10
    One thing to be aware of is that compiling for the simulator vs. the device can cause surprising changes in these macros. When compiling for the simulator SDK 2.2.1 I get __IPHONE_OS_VERSION_MIN_REQUIRED = 20000. When compiling for the device, however, I get __IPHONE_OS_VERSION_MIN_REQUIRED = 20201, which breaks the condition you've defined above. I'm currently using plain "#ifdef __IPHONE_3_0" to isolate code that only works in 3.0 or higher. That works because the macro isn't defined until the 3.0 SDK. – n8gray May 29 '09 at 05:34
  • 5
    Careful with the run-time code. By calling floatValue, you will only get 3.20000, even if the actual version is 3.2.2. – Joseph Tura Nov 17 '10 at 14:44
  • Why do I get __IPHONE_OS_VERSION_MIN_REQUIRED = 30200 when I build & run on iPhone (4.3.1) using Xcode 4? – ma11hew28 Jul 07 '11 at 20:13
  • 3
    The run-time code in your answer is plain wrong. Float values and strings have different orderings: `3.10 < 3.2`, but `"3.10" > "3.2"`. Furthermore, the version string may have more than two components (for example, 5.0.1, which is used in many apps to exclude files from iCloud backup). The right way to do a version check is to use `[systemVersion compare:version options:NSNumericSearch]`. – yakovlev Aug 22 '12 at 20:59
  • Version numbers aren't floats, or decimal numbers at all. Version numbers are integers, delimited by dot character. – David Pisoni Feb 15 '13 at 18:33
  • Why not `#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0`? – Ky - Jan 12 '16 at 18:59
19

I'd be careful with the floatValue return result:

[[[UIDevice currentDevice] systemVersion] floatValue]

As with any floats, it may not be exactly what you expect. When running the above on my system, confused why my conditional statement wasn't executing, I noticed the value returned was:

3.20000005

Recommend the solutions here instead: How to check iOS version?

Excerpt:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}
Community
  • 1
  • 1
Drennyn
  • 201
  • 2
  • 3
  • Is the `3.2.00..005` still a problem with `doubleValue`? – Ky - Jan 12 '16 at 19:03
  • @BenC.R.Leggiero it should be. It's impossible to represented 3.2 exactly in binary, no matter how much precision you use. – Brennan Vincent Aug 18 '16 at 21:26
  • @BrennanVincent I think you mean with IEEE floats, since it's trivial to represent using `NSDecimalNumber` – Ky - Nov 09 '16 at 14:18
  • @BenLeggiero I said in binary. NSDecimalNumber is not "binary"; it's binary-coded decimal. My statement was about mathematics, not computer technology. `double` is binary, so it is mathematically impossible for it to represent 3.2 precisely. – Brennan Vincent Nov 10 '16 at 22:03
6

UPDATE: When building & running on iPhone (4.3.1) using Xcode 4, this no longer seems to work for me. Also, I get __IPHONE_OS_VERSION_MIN_REQUIRED = 30200.

The iPhone Developer's Cookbook says you can also do:

#ifdef _USE_OS_4_OR_LATER
    // code to compile for 4.0 or later
#else
    // code to compile for pre-4.0
#endif

And, it seems to work for me. :)

ma11hew28
  • 121,420
  • 116
  • 450
  • 651
4

Pretty sure you can also do:

#ifdef __IPHONE_3_0
// 3.0 code here
#endif
BadPirate
  • 25,802
  • 10
  • 92
  • 123
0

It's in Xcode's build options. The drop down on the top left corner that says something like "myapp - 3.0 | Debug" Select the build you want and presto, your done.

Robert Gould
  • 68,773
  • 61
  • 187
  • 272
  • The problem with that method is that I want my app to work on 2.2.1 aswell, with only this one line of code running on 3.0. Your method would mean I'd have to drop support for 2.2x. – Oliver May 04 '09 at 13:53
  • I see what you mean now, tricky, but you might be able to make a pinpoint check then. Say check for a define in a header. – Robert Gould May 04 '09 at 23:43
0

Using the trick of adding OTHER_CFLAGS = "-g3 -save-temps -dD" from this answer, I found that the define __IPHONE_OS_VERSION_MIN_REQUIRED 20000 with a project targeted at 2.2.1. Perhaps that will work?

Community
  • 1
  • 1
Jeff Youel
  • 653
  • 4
  • 7
0

I'm fairly certain that the comment on the OP sums it up. You can't. Because a compile time directive cannot make a run-time decision. In Xcode, if you target 3.0, it won't run on a 2.2.1 phone. If you target 2.2.1, it won't compile because you have 3.0 specific code in there.

The only true solution would be two versions of your app, one of which is compiled for 3.0, and the other for 2.2.1.

mmc
  • 17,354
  • 2
  • 34
  • 52
  • 1st: the OP is actually not excluding compile-time-checks. 2nd: There are exceptions to your given rule. As an example, the MPMoviePlayerController exists on 3.0 and on 3.2 but works differently on 3.2 (and 4.0) - to properly support it on both platforms, I found using a runtime-os-version-check very handy. In my special case, omitting this check will still lead to a proper build on both platforms, but will crash on anything below 3.2. – Till Aug 26 '10 at 09:53
-2

Well, my two cents:

How about building your app with the latest version say 3.0 so you can exploit all the new & cool APIs and specifying the Deployment Target as the least recent version you want to support so guys out there who didn't take time out to upgrade their devices will stil run your app. In this case as shown above you need to check for least recent version of the SDK and provide alternate functionality to make your application backward compatible.

Regards, Hardik