46

This is sort of a follow on from my last question. I am using beginAnimations:context: to setup an animation block to animate some UITextLabels. However I noticed in the docs that is says: "Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods instead."

My question is I would love to use animateWithDuration:animations: (available in iOS 4.0 and later) but do not want to exclude folks using iOS 3.0. Is there a way to check to iOS version of a device at runtime so that I can make a decision as to which statement to use?

fuzzygoat
  • 26,573
  • 48
  • 165
  • 294

11 Answers11

58

Simpler solution for anyone who'll need help in the future:

NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];

if ( 5 == [[versionCompatibility objectAtIndex:0] intValue] ) { /// iOS5 is installed

    // Put iOS-5 code here

} else { /// iOS4 is installed

    // Put iOS-4 code here         

}
ArtSabintsev
  • 5,170
  • 10
  • 41
  • 71
  • 3
    you could also have used the `NSNumericSearch` compare option ;) http://stackoverflow.com/a/1990854/429521 – Felipe Sabino Nov 23 '12 at 17:39
  • This is great because unlike the current accepted answer I need to know which iOs version the user is operating because certain unicode character are functioning differently pre iOS6 (like /u200b which has a length of 0 on periOS6 but a length of 1 on postiOS6) – Albert Renshaw Feb 14 '13 at 14:52
  • 3
    It should also be noted that you should say `if (5 <= ...)` this way if they come out with a newer iOs version (i.e. iOS6) your app will still support your features! – Albert Renshaw Feb 14 '13 at 14:58
  • Yes, very true. I wrote that in a rush last year. I'm going to adjust it now. – ArtSabintsev Feb 14 '13 at 16:54
  • 1
    Actually, I'll leave that as an exercise to the reader. Maybe they want something specific in iOS 6, that's not in iOS 5, so they'll have to modify it anyway. Thank you for your suggestion and kind words. – ArtSabintsev Feb 14 '13 at 16:56
51

In many cases you do not need to check iOS version directly, instead of that you can check whether particular method is present in runtime or not.

In your case you can do the following:

if ([[UIView class] respondsToSelector:@selector(animateWithDuration:animations:)]){
// animate using blocks
}
else {
// animate the "old way"
}
Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • 1
    `[[UIView class] respondsToSelector:@selector(animateWithDuration:animations:)]` can be written as `[UIView respondsToSelector:@selector(animateWithDuration:animations:)]` – user102008 Jun 12 '12 at 21:59
  • 10
    I hate blanket statements. There are use cases where you must check the iOS version. I'm facing such a use case right now!!! – Justin Kredible Jul 07 '12 at 19:14
  • @JohnConnor, you're right in some cases you may need to check iOS version but in general you should avoid that if possible. Just curious, what's your case? – Vladimir Jul 15 '12 at 12:59
  • @JustinKredible, me too. In my case, if Location Services is disabled/denied for my app, I want to proactively direct them to the Settings App ... except the options differ between iOS 5 and iOS 6. How else will I be able to give the user proper direction than through knowing if they're on iOS 6 or not? – Joe D'Andrea Oct 24 '12 at 19:11
19

to conform to version specified in system defines

//#define __IPHONE_2_0 20000
//#define __IPHONE_2_1 20100
//#define __IPHONE_2_2 20200
//#define __IPHONE_3_0 30000
//#define __IPHONE_3_1 30100
//#define __IPHONE_3_2 30200
//#define __IPHONE_4_0 40000
You can write function like this ( you should probably store this version somewhere rather than calculate it each time ):

+ (NSInteger) getSystemVersionAsAnInteger{
    int index = 0;
    NSInteger version = 0;

    NSArray* digits = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    NSEnumerator* enumer = [digits objectEnumerator];
    NSString* number;
    while (number = [enumer nextObject]) {
        if (index>2) {
            break;
        }
        NSInteger multipler = powf(100, 2-index);
        version += [number intValue]*multipler;
        index++;
    }
return version;
}

Then you can use this as follows:

if([Toolbox getSystemVersionAsAnInteger] >= __IPHONE_4_0)
{
  //blocks
} else 
{
  //oldstyle
}
RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
11

Xcode 7 added the available syntax making this relatively more simple:

Swift:

if #available(iOS 9, *) {
    // iOS 9 only code
} 
else {
   // Fallback on earlier versions
}

Xcode 9 also added this syntax to Objective-C

Objective-C:

if (@available(iOS 9.0, *)) {
   // iOS 9 only code
} else {
   // Fallback on earlier versions
}
mokagio
  • 16,391
  • 3
  • 51
  • 58
Leon Lucardie
  • 9,541
  • 4
  • 50
  • 70
7

Most of these solutions on here are so overkill. All you need to do is [[UIDevice currentDevice].systemVersion intValue]. This automatically removes the decimal, so there is no need to split the string.

So you can just check it like:

if ([[UIDevice currentDevice].systemVersion intValue] >= 8) {
    // iOS 8.0 and above
} else {
    // Anything less than iOS 8.0
}

You can also define a macro with this code:

#define IOS_VERSION [[UIDevice currentDevice].systemVersion intValue];

or even include your check:

#define IOS_8PLUS ([[UIDevice currentDevice].systemVersion intValue] >= 8)

Then you just need to do:

if (IOS_8PLUS) {
    // iOS 8.0 and above
} else {
    // Anything less than iOS 8.0
}
Firo
  • 15,448
  • 3
  • 54
  • 74
6

You can use the version of the Foundation framework to determine the current system version.

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1){

//for earlier versions

} else {

//for iOS 7

}
SGRKDL
  • 106
  • 1
  • 2
6

Discouraged is not the same as deprecated.

If you need to support earlier versions of iOS that do not have the block based methods, there is nothing wrong with using the older methods (as long as they haven't been removed, of course).

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • Honestly, if you don't need the features of the block based methods, I see nothing wrong with the older method. – Jonny Oct 29 '10 at 03:04
  • Suggest this be made into a comment or useful information added to make this an answer. Unsure why it's up voted... – Tommie C. Jul 29 '14 at 15:23
3

For my purposes I've written a tiny library that abstracts away the underlying C calls and presents an Objective-C interface.

GBDeviceDetails deviceDetails = [GBDeviceInfo deviceDetails];
if (deviceDetails.iOSVersion >= 6) {
    NSLog(@"It's running at least iOS 6");      //It's running at least iOS 6
}

Apart from getting the current iOS version, it also detects the hardware of the underlying device, and gets info about the screen size; all at runtime.

It's on github: GBDeviceInfo. Licensed under Apache 2.

lmirosevic
  • 15,787
  • 13
  • 70
  • 116
2

Put this in your Prefix.pch file

#define IOS_VERSION [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] firstObject] intValue]

And then you can check iOS versions like:

if(IOS_VERSION == 8)
{
     // Hello 8!
}
else
{
     // Hello some other version!
}

Off course if you can use feature detection (and it makes sense for your use case) you should do that.

Matthijn
  • 3,126
  • 9
  • 46
  • 69
1

In MonoTouch:

To get the Major version use:

UIDevice.CurrentDevice.SystemVersion.Split('.')[0]

For minor version use:

UIDevice.CurrentDevice.SystemVersion.Split('.')[1]
callisto
  • 4,921
  • 11
  • 51
  • 92
1

A bit nicer and more efficient adaptation to the above solutions:

-(CGPoint)getOsVersion
{
    static CGPoint rc = {-1,-1};
    if (rc.x == -1) {
        NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
        rc.x = [versionCompatibility[0] intValue];
        rc.y = [versionCompatibility[1] intValue];
    }
    return rc;
}

now you can

if ([self getOsVersion].x < 7) {
}

HTH

ishahak
  • 6,585
  • 5
  • 38
  • 56