The right way to check the iOS version in an app


Update 2018-03-02: if you’re developing in Swift, you should use availability checking. For example:

if #available(iOS 11.0, *) {
    // use iOS 11-only feature
} else {
    // handle older versions
}

The other day, I added UIAppearance to an app. It made my life so much simpler – I deleted a ton of code and just set the tint color and a few other properties in one place, rather than having tint color setters scattered all over the codebase. In doing this, I learned that UIAppearance behaves differently (and provides different methods) on iOS 6 and iOS 7. So, naturally, I needed to figure out whether my app was running on iOS 6 or iOS 7 in order to set the appearance properties appropriately. So I searched for “iOS version check” and found this Stack Overflow question, which addresses my question.

Unfortunately, the accepted and the highest-voted answers on that question and this one may have been correct back in the iOS 3 days, but they’re incorrect today. And, alas, it seems like lots of people are still using this, as I’ve seen it in recent code bases and examples all over the internet. Let’s hope this article can help to set things straight – for everyone’s sake.

The wrong way to do an iOS version check

Don’t use this code to check the iOS version in your app. Let me repeat: DO NOT check the iOS version this way:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
    // Load resources for iOS 7 or later
}
else
{
    // Load resources for iOS 6.1 or earlier
}

Why, you ask? A fine question. Luckily, there’s some good stuff in the Stack Overflow comments. If you had stumbled across the question in your search and didn’t read the comments on each answer, you missed something important:

Um, no. This is wrong in a couple of important ways. 1: Version numbers aren’t always a simple floating-point number, for example “4.2.1” is a valid iOS version number. 2: You’re doing raw floating point comparison. Due to the finite precision of floating point numbers, your comparison may fail (or succeed) when you wouldn’t otherwise expect it to. – Mac

So, to summarize: why should you not use the float value of the systemVersion? Because you may get unexpected results. And those unexpected results can lead to crashes, bugs, or just plain weird behavior.

The right way to do an iOS version check

Instead, use the following code to check the iOS version, per Apple’s suggestion:

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
{
    // Load resources for iOS 6.1 or earlier
}
else
{
    // Load resources for iOS 7 or later
}

Or, if you'd to use that in multiple places in your code (per the DRY principle), put it in a method:

+ (BOOL)isIOS7OrHigher
{
    float versionNumber = floor(NSFoundationVersionNumber);
    return versionNumber > NSFoundationVersionNumber_iOS_6_1;
}

Assuming that's in a class called RFSUtilities, you can use it in if statements all over your code, like this:

if ([RFSUtilities isIOS7OrHigher])
{
    // Load resources for iOS 7 or later
}
else
{
    // Load resources for iOS 6.1 or lower
}

And there you have it - the correct, Apple-recommended way to check what version of iOS your app is running on.

Stack Overflow is great for figuring out how to do things in iOS, but the best answers don't always rise to the top, especially on older questions. Don't get stuck doing things the wrong way on iOS and have them come back to bite you later. If you want to make sure you're doing things the right way, the safe way, the way Apple recommends, put your name and email in the box below to get more like this. You'll also get to build up your Swift skills with the free 5-Part Guide to Getting Started.