Sometimes you may need to modify your app’s behavior depending on which OS version it’s running on. As of XCode 3.2 you can choose a different SDK to compile against than you choose for the deployment target. This allows to make an app that runs as low as 2.0, but uses all the bug fixes in the SDKs. And it forces the compiler to make dynamic links to 3.x frameworks. So you can check at run time if such a framework is available and if not present the feature that depends on it.
When working on DTAugmentedRealityController I needed to limit it’s use on devices with a magnetometer and also which run a version of iPhoneOS that’s greater than or equal to 3.1 because this is the version when Apple introduced the capability of overlaying your own view on top of an UIImagePickerController. So I needed an elegant method, I would not settle for comparing strings. That’s why I came up with this extension to UIDevice.
UIDevice gives you an instance of the current device and this you can query for the systemVersion. Though this is just an NSString. Checking this against all possible versions would be unfeasable and simply converting it to a double would not work either. The reason being that the number of digits in the minor version does not have to be one. And then 3.12 would be less than 3.1. Granted, Apple would probably not make that many minor versions before making a major one. But, hey, if you create an extension, then make something that works for all version numbers conceivable.
Since I want to be able to check major and minor version number separately but only query UIDevice once, I defined a new struct type to hold all three parts of the version number which are separated by a period.
UIDevice+DTVersion.h
typedef struct { NSInteger major; NSInteger minor; NSInteger point; } DTVersion; @interface UIDevice (DTVersion) - (DTVersion) osVersion; @end |
The osVersion method is supposed to be filling in the numbers and returning this structure. A little bit of smart splitting, non-existent parts to be zeroed.
UIDevice+DTVersion.m
#import "UIDevice+DTVersion.h" @implementation UIDevice (DTVersion) - (DTVersion) osVersion { NSString *versionString = [self systemVersion]; NSArray *parts = [versionString componentsSeparatedByString:@"."]; DTVersion retVersion; NSUInteger partCount = [parts count]; retVersion.major = (partCount>0)?[[parts objectAtIndex:0] intValue]:0; retVersion.minor = (partCount>1)?[[parts objectAtIndex:1] intValue]:0; retVersion.point = (partCount>2)?[[parts objectAtIndex:2] intValue]:0; return retVersion; } @end |
To try it out simple add the above code to your project, import the header in your own project and do the following:
DTVersion osVersion = [[UIDevice currentDevice] osVersion]; NSLog(@"major: %d minor: %d point: %d", osVersion.major, osVersion.minor, osVersion.point); BOOL greaterThan31 = (osVersion.major>3) || ((osVersion.major==3)&&(osVersion.minor>=1)); if (greaterThan31) { // special code that requires Version >= 3.1 } |
Sure, you could paste the code from osVersion to where the version checking takes place. But I feel it’s generally smarter to package a helper method like this in a category extension so as to have less clutter in your source.
Categories: Recipes