How to check iOS Version is iOS 6? [duplicate] - ios

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Check iPhone iOS Version
I want to check iOS Version in iOS.
Because i have some of codes only for iOS 6.
So how can i?

Check this GitHub Gist
https://gist.github.com/998472
You can add the code or include it in your ...-Prefix.pch file so you can use it wherever you need it.
EDIT
I'm leaving an example of how you can use the code from Gist so people can check if it's useful for their case. This can also be found over the Gist.
/*
* Usage
*/
if (SYSTEM_VERSION_LESS_THAN(#"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"3.1.1")) {
...
}

Try this:
Update:
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ([[vComp objectAtIndex:0] intValue] >= 7) {
// iOS-7 code[current] or greater
} else if ([[vComp objectAtIndex:0] intValue] == 6) {
// iOS-6 code
} else if ([[vComp objectAtIndex:0] intValue] > 2) {
// iOS-3,4,5 code
} else {
// iOS-1,2... code: incompatibility warnings, legacy-handlers, etc..
}
Previous code:
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ([[vComp objectAtIndex:0] intValue] == 6) {
// iOS-6 code
} else {
// iOS-5, iOS-4... code
}
To specifically check for a subversion of IOS use
float sysVer = [[[UIDevice currentDevice] systemVersion] floatValue];
if (sysVer > 6.01) {
// iOS-6.01+ code
} else {
// prior iOS versions
}

You can get the iOS version as a string using:
[[UIDevice currentDevice] systemVersion]

Related

iOS7 app backward compatible with iOS5 regarding unique identifier

My app is compatible with iOS5 and iOS6.
Until now I had no problem using:
NSString DeviceID = [[UIDevice currentDevice] uniqueIdentifier];
Now with iOS7 and with uniqueIdentifier not working anymore I changed to:
NSString DeviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
The problem is, this would not work for iOS5.
How can I achieve backward compatibility with iOS5?
I tried this, with no luck:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
// iOS 6.0 or later
NSString DeviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
#else
// iOS 5.X or earlier
NSString DeviceID = [[UIDevice currentDevice] uniqueIdentifier];
#endif
The best and recommend option by Apple is:
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
Use it for every device above 5.0.
For 5.0 you have to use uniqueIdentifier. The best to check if it's available is:
if (!NSClassFromString(#"ASIdentifierManager"))
Combining that will give you:
- (NSString *) advertisingIdentifier
{
if (!NSClassFromString(#"ASIdentifierManager")) {
SEL selector = NSSelectorFromString(#"uniqueIdentifier");
if ([[UIDevice currentDevice] respondsToSelector:selector]) {
return [[UIDevice currentDevice] performSelector:selector];
}
//or get macaddress here http://iosdevelopertips.com/device/determine-mac-address.html
}
return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}
Why just not to use CFUUIDRef and be independent with iOS verion?
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
self.uuidString = (NSString *)CFUUIDCreateString(NULL,uuidRef);
CFRelease(uuidRef);
And of course remember calculated uuidString in the Keychain(in case of application removal)?
Here is written how to use keychain
As hard replacement of static macro, you can try dynamic if statement to check it.
UIDevice has property named 'systemVersion' and you can check this.

The [UIDevice uniqueIdentifier] become private in iOS 6.0

Apple doesn't allowed to add application to the app store that used the [UIDevice uniqueIdentifier] because the property become private in iOS SDK 6.0
What are the Alternatives?
you can use/create "your own" UDID:
+(NSString *)getUUID
{
CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
NSString * uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);
CFRelease(newUniqueId);
return uuidString;
}
You should keep in mind that this method will produce a different id on every call so you should persist it some how, thus it is not an identical alternative to the UDID, but for most uses it is even better like that.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
- (NSString*)deviceId {
NSString *udidString;
if (SYSTEM_VERSION_LESS_THAN(#"6.0")) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
udidString = [defaults objectForKey:#"udidKey"];
if (!udidString) {
CFUUIDRef identifierObject = CFUUIDCreate(kCFAllocatorDefault);
// Convert the CFUUID to a string
udidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, identifierObject);
[defaults setObject:udidString forKey:#"udidKey"];
[defaults synchronize];
CFRelease((CFTypeRef) identifierObject);
}
} else {
udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return udidString;
}
if gets warning on the line: udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; it means the Xcode SDK is less than 6.0
(Xcode 4.3 contains iOS SDK 5.1, Xcode 4.5 contains iOS SDK 6.0)
to update Xcode iOS SDK:
simply download the newest Xcode available on App Store (Apple doesn't give an option to download only the SDK).
if want to keep current Xcode version just:
download the newest Xcode version.
copy iOS SDK Library from :
newestXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
to
oldXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
Reopen old Xcode and thats it!

uniqueIdentifier vs. indentifierForVendor and Apple rejection

I have a question about uniqueIdentifier vs identifierforVendor. We use the UDID for login identification purposes and we are in the process of switching over to the new iOS 6 version of forVendor...
My questions are this
1) Is Apple rejecting apps that are still using uniqueIdentifier?
2) How can they reject this seeing as they don't allow first generation ipads to go up to 6.0?
PS - also found that identifierforVendor doesn't always work in 6.0, looks like it was resolved in 6.0.1
Here is the code I am using... do you think it will get rejected?
static inline NSString* UniqueDeviceId() {
if ([[[UIDevice currentDevice] systemVersion] compare:#"6.0.1" options:NSNumericSearch] != NSOrderedAscending)
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
return [[UIDevice currentDevice] uniqueIdentifier];
}
thanks
While I can't speak for the Apple review team. it is unlikely you will be rejected for using this deprecated API as long as your app supports a version of iOS that doesn't have the alternative.
I would update your code to properly check for the new method:
if ([[UIDevice currentDevice] respondsToSelector:#selector(identifierForVendor)]) {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
} else {
return [[UIDevice currentDevice] uniqueIdentifier];
}
now Apps are not permitted to access the UDID and must not use the uniqueIdentifier method of UIDevice. Please update your apps and servers to associate users with the Vendor or Advertising identifiers introduced in iOS 6
NSUUID *uuid = [[UIDevice currentDevice] identifierForVendor];
NSString *uuidString = [uuid UUIDString];
and must to add ADSupport framework

How to check iOS version?

I want to check if the iOS version of the device is greater than 3.1.3
I tried things like:
[[UIDevice currentDevice].systemVersion floatValue]
but it does not work, I just want a:
if (version > 3.1.3) { }
How can I achieve this?
/*
* System Versioning Preprocessor Macros
*/
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
/*
* Usage
*/
if (SYSTEM_VERSION_LESS_THAN(#"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"3.1.1")) {
...
}
The quick answer …
As of Swift 2.0, you can use #available in an if or guard to protect code that should only be run on certain systems.
if #available(iOS 9, *) {}
In Objective-C, you need to check the system version and perform a comparison.
[[NSProcessInfo processInfo] operatingSystemVersion] in iOS 8 and above.
As of Xcode 9:
if (#available(iOS 9, *)) {}
The full answer …
In Objective-C, and Swift in rare cases, it's better to avoid relying on the operating system version as an indication of device or OS capabilities. There is usually a more reliable method of checking whether a particular feature or class is available.
Checking for the presence of APIs:
For example, you can check if UIPopoverController is available on the current device using NSClassFromString:
if (NSClassFromString(#"UIPopoverController")) {
// Do something
}
For weakly linked classes, it is safe to message the class, directly. Notably, this works for frameworks that aren't explicitly linked as "Required". For missing classes, the expression evaluates to nil, failing the condition:
if ([LAContext class]) {
// Do something
}
Some classes, like CLLocationManager and UIDevice, provide methods to check device capabilities:
if ([CLLocationManager headingAvailable]) {
// Do something
}
Checking for the presence of symbols:
Very occasionally, you must check for the presence of a constant. This came up in iOS 8 with the introduction of UIApplicationOpenSettingsURLString, used to load Settings app via -openURL:. The value didn't exist prior to iOS 8. Passing nil to this API will crash, so you must take care to verify the existence of the constant first:
if (&UIApplicationOpenSettingsURLString != NULL) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
Comparing against the operating system version:
Let's assume you're faced with the relatively rare need to check the operating system version. For projects targeting iOS 8 and above, NSProcessInfo includes a method for performing version comparisons with less chance of error:
- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version
Projects targeting older systems can use systemVersion on UIDevice. Apple uses it in their GLSprite sample code.
// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = #"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
displayLinkSupported = TRUE;
}
If for whatever reason you decide that systemVersion is what you want, make sure to treat it as an string or you risk truncating the patch revision number (eg. 3.1.2 -> 3.1).
As suggested by the official Apple docs: you can use the NSFoundationVersionNumber, from the NSObjCRuntime.h header file.
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
// here you go with iOS 7
}
Starting Xcode 9, in Objective-C:
if (#available(iOS 11, *)) {
// iOS 11 (or newer) ObjC code
} else {
// iOS 10 or older code
}
Starting Xcode 7, in Swift:
if #available(iOS 11, *) {
// iOS 11 (or newer) Swift code
} else {
// iOS 10 or older code
}
For the version, you can specify the MAJOR, the MINOR or the PATCH (see http://semver.org/ for definitions). Examples:
iOS 11 and iOS 11.0 are the same minimal version
iOS 10, iOS 10.3, iOS 10.3.1 are different minimal versions
You can input values for any of those systems:
iOS, macOS, watchOS, tvOS
Real case example taken from one of my pods:
if #available(iOS 10.0, tvOS 10.0, *) {
// iOS 10+ and tvOS 10+ Swift code
} else {
// iOS 9 and tvOS 9 older code
}
documentation
Try:
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
}
Preferred Approach
In Swift 2.0 Apple added availability checking using a far more convenient syntax (Read more here). Now you can check the OS version with a cleaner syntax:
if #available(iOS 9, *) {
// Then we are on iOS 9
} else {
// iOS 8 or earlier
}
This is the preferred over checking respondsToSelector etc (What's New In Swift). Now the compiler will always warn you if you aren't guarding your code properly.
Pre Swift 2.0
New in iOS 8 is NSProcessInfo allowing for better semantic versioning checks.
Deploying on iOS 8 and greater
For minimum deployment targets of iOS 8.0 or above, use NSProcessInfo
operatingSystemVersion or isOperatingSystemAtLeastVersion.
This would yield the following:
let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)
if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {
//current version is >= (8.1.2)
} else {
//current version is < (8.1.2)
}
Deploying on iOS 7
For minimum deployment targets of iOS 7.1 or below, use compare with
NSStringCompareOptions.NumericSearch on UIDevice systemVersion.
This would yield:
let minimumVersionString = "3.1.3"
let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)
switch versionComparison {
case .OrderedSame, .OrderedDescending:
//current version is >= (3.1.3)
break
case .OrderedAscending:
//current version is < (3.1.3)
fallthrough
default:
break;
}
More reading at NSHipster.
I always keep those in my Constants.h file:
#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#define IS_OS_5_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{
// eg NSString *reqSysVer = #"4.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
{
return YES;
}else{
return NO;
}
}
With Version class that is contained in nv-ios-version project (Apache License, Version 2.0), it is easy to get and compare iOS version. An example code below dumps the iOS version and checks whether the version is greater than or equal to 6.0.
// Get the system version of iOS at runtime.
NSString *versionString = [[UIDevice currentDevice] systemVersion];
// Convert the version string to a Version instance.
Version *version = [Version versionWithString:versionString];
// Dump the major, minor and micro version numbers.
NSLog(#"version = [%d, %d, %d]",
version.major, version.minor, version.micro);
// Check whether the version is greater than or equal to 6.0.
if ([version isGreaterThanOrEqualToMajor:6 minor:0])
{
// The iOS version is greater than or equal to 6.0.
}
// Another way to check whether iOS version is
// greater than or equal to 6.0.
if (6 <= version.major)
{
// The iOS version is greater than or equal to 6.0.
}
Project Page: nv-ios-version
TakahikoKawasaki/nv-ios-version
Blog: Get and compare iOS version at runtime with Version class
Get and compare iOS version at runtime with Version class
I know this is an old question, but someone should have mentioned the compile-time macros in Availability.h. All of the other methods here are runtime solutions, and will not work in a header file, class category, or ivar definition.
For these situations, use
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 && defined(__IPHONE_14_0)
// iOS 14+ code here
#else
// Pre iOS 14 code here
#endif
h/t this answer
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
// Your code here
}
Where of course, NSFoundationVersionNumber_iOS_6_1 must be changed to by applicable for the iOS version you want to check. What I have now written will probably be used a lot when testing if a device is running iOS7 or a previous version.
New way to check the system version using the swift Forget [[UIDevice currentDevice] systemVersion] and NSFoundationVersionNumber.
We can use NSProcessInfo -isOperatingSystemAtLeastVersion
import Foundation
let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
a bit late to the party but in light of iOS 8.0 out there this might be relevant:
if you can avoid using
[[UIDevice currentDevice] systemVersion]
Instead check for existence of of a method/class/whatever else.
if ([self.yourClassInstance respondsToSelector:#selector(<yourMethod>)])
{
//do stuff
}
I found it to be useful for location manager where I have to call requestWhenInUseAuthorization for iOS 8.0 but the method is not available for iOS < 8
UIDevice+IOSVersion.h
#interface UIDevice (IOSVersion)
+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
#end
UIDevice+IOSVersion.m
#import "UIDevice+IOSVersion.h"
#implementation UIDevice (IOSVersion)
+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion
{
return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;
}
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion
{
return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedDescending;
}
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion
{
return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;
}
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion
{
return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;
}
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
{
return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;
}
#end
Just for retrieving the OS version string value:
[[UIDevice currentDevice] systemVersion]
In general it's better to ask if an object can perform a given selector, rather than checking a version number to decide if it must be present.
When this is not an option, you do need to be a bit careful here because [#"5.0" compare:#"5" options:NSNumericSearch] returns NSOrderedDescending which might well not be intended at all; I might expect NSOrderedSame here. This is at least a theoretical concern, one that is worth defending against in my opinion.
Also worth considering is the possibility of a bad version input which can not reasonably be compared to. Apple supplies the three predefined constants NSOrderedAscending, NSOrderedSame and NSOrderedDescending but I can think of a use for some thing called NSOrderedUnordered in the event I can't compare two things and I want to return a value indicating this.
What's more, it's not impossible that Apple will some day expand their three predefined constants to allow a variety of return values, making a comparison != NSOrderedAscending unwise.
With this said, consider the following code.
typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;
#interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
#end
#implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:#".."].location != NSNotFound ||
[vTwo rangeOfString:#".."].location != NSNotFound) {
return SKOrderedNotOrdered;
}
NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:#".0123456789"];
NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
return SKOrderedNotOrdered;
}
NSArray *vOneArray = [vOne componentsSeparatedByString:#"."];
NSArray *vTwoArray = [vTwo componentsSeparatedByString:#"."];
for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
if (vOneInt > vTwoInt) {
return kSKOrderedDescending;
} else if (vOneInt < vTwoInt) {
return kSKOrderedAscending;
}
}
if ([vOneArray count] > [vTwoArray count]) {
for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
if ([[vOneArray objectAtIndex:i] intValue] > 0) {
return kSKOrderedDescending;
}
}
} else if ([vOneArray count] < [vTwoArray count]) {
for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
return kSKOrderedAscending;
}
}
}
return kSKOrderedSame;
}
#end
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
if (_kisiOS7) {
NSLog(#"iOS7 or greater")
}
else {
NSLog(#"Less than iOS7");
}
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
Then add a if condition as follows:-
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"10.0")) {
//Your code
}
There are version like 7.0 or 6.0.3, so we can simply convert version into numerics to compare. if version is like 7.0, simply append another ".0" to it and then take its numeric value.
int version;
NSString* iosVersion=[[UIDevice currentDevice] systemVersion];
NSArray* components=[iosVersion componentsSeparatedByString:#"."];
if ([components count]==2) {
iosVersion=[NSString stringWithFormat:#"%#.0",iosVersion];
}
iosVersion=[iosVersion stringByReplacingOccurrencesOfString:#"." withString:#""];
version=[iosVersion integerValue];
For 6.0.0
if (version==600) {
// Do something
}
for 7.0
if (version==700) {
// Do something
}
Try the below code:
NSString *versionString = [[UIDevice currentDevice] systemVersion];
As a variation of yasimturks solution, I defined one function and a few enum values instead of five macros. I find it more elegant, but that's a matter of taste.
Usage:
if (systemVersion(LessThan, #"5.0")) ...
.h file:
typedef enum {
LessThan,
LessOrEqual,
Equal,
GreaterOrEqual,
GreaterThan,
NotEqual
} Comparison;
BOOL systemVersion(Comparison test, NSString* version);
.m file:
BOOL systemVersion(Comparison test, NSString* version) {
NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
switch (test) {
case LessThan: return result == NSOrderedAscending;
case LessOrEqual: return result != NSOrderedDescending;
case Equal: return result == NSOrderedSame;
case GreaterOrEqual: return result != NSOrderedAscending;
case GreaterThan: return result == NSOrderedDescending;
case NotEqual: return result != NSOrderedSame;
}
}
You should add your app's prefix to the names, especially to the Comparison type.
Using the refered recommended way... if there is no definition in the header files, you can always get the versión printing it on console with a device of the desired IOS versión.
- (BOOL) isIOS8OrAbove{
float version802 = 1140.109985;
float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
NSLog(#"la version actual es [%f]", NSFoundationVersionNumber);
if (NSFoundationVersionNumber >= version8){
return true;
}
return false;
}
Solution for checking iOS version in Swift
switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
case .OrderedAscending:
println("iOS < 8.0")
case .OrderedSame, .OrderedDescending:
println("iOS >= 8.0")
}
Con of this solution: it is simply bad practice to check against OS version numbers, whichever way you do it. One should never hard code dependencies in this way, always check for features, capabilities or the existence of a class. Consider this; Apple may release a backwards compatible version of a class, if they did then the code you suggest would never use it as your logic looks for an OS version number and NOT the existence of the class.
(Source of this information)
Solution for checking the class existence in Swift
if (objc_getClass("UIAlertController") == nil) {
// iOS 7
} else {
// iOS 8+
}
Do not use if (NSClassFromString("UIAlertController") == nil) because it works correctly on the iOS simulator using iOS 7.1 and 8.2, but if you test on a real device using iOS 7.1, you will unfortunately notice that you will never pass through the else part of the code snippet.
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
A more generic version in Obj-C++ 11 (you could probably replace some of this stuff with the NSString/C functions, but this is less verbose. This gives you two mechanisms. splitSystemVersion gives you an array of all the parts which is useful if you just want to switch on the major version (e.g. switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }).
#include <boost/lexical_cast.hpp>
- (std::vector<int>) splitSystemVersion {
std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
std::vector<int> versions;
auto i = version.begin();
while (i != version.end()) {
auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
std::string versionPart(i, nextIllegalChar);
i = std::find_if(nextIllegalChar, version.end(), isdigit);
versions.push_back(boost::lexical_cast<int>(versionPart));
}
return versions;
}
/** Losslessly parse system version into a number
* #return <0>: the version as a number,
* #return <1>: how many numeric parts went into the composed number. e.g.
* X.Y.Z = 3. You need this to know how to compare again <0>
*/
- (std::tuple<int, int>) parseSystemVersion {
std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
int versionAsNumber = 0;
int nParts = 0;
auto i = version.begin();
while (i != version.end()) {
auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
std::string versionPart(i, nextIllegalChar);
i = std::find_if(nextIllegalChar, version.end(), isdigit);
int part = (boost::lexical_cast<int>(versionPart));
versionAsNumber = versionAsNumber * 100 + part;
nParts ++;
}
return {versionAsNumber, nParts};
}
/** Assume that the system version will not go beyond X.Y.Z.W format.
* #return The version string.
*/
- (int) parseSystemVersionAlt {
std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
int versionAsNumber = 0;
int nParts = 0;
auto i = version.begin();
while (i != version.end() && nParts < 4) {
auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
std::string versionPart(i, nextIllegalChar);
i = std::find_if(nextIllegalChar, version.end(), isdigit);
int part = (boost::lexical_cast<int>(versionPart));
versionAsNumber = versionAsNumber * 100 + part;
nParts ++;
}
// don't forget to pad as systemVersion may have less parts (i.e. X.Y).
for (; nParts < 4; nParts++) {
versionAsNumber *= 100;
}
return versionAsNumber;
}
Try this
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// do some work
}
float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
float versionToBeCompared = 3.1.3; //(For Example in your case)
if(deviceOSVersion < versionToBeCompared)
//Do whatever you need to do. Device version is lesser than 3.1.3(in your case)
else
//Device version should be either equal to the version you specified or above
Swift example that actually works:
switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
println("iOS >= 8.0")
case .OrderedAscending:
println("iOS < 8.0")
}
Don't use NSProcessInfo cause it doesn't work under 8.0, so its pretty much useless until 2016
Here is a swift version:
struct iOSVersion {
static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}
Usage:
if iOSVersion.iOS8 {
//Do iOS8 code here
}
Here is a Swift version of yasirmturk macros. Hope it helps some peoples
// MARK: System versionning
func SYSTEM_VERSION_EQUAL_TO(v: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}
func SYSTEM_VERSION_GREATER_THAN(v: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}
func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}
func SYSTEM_VERSION_LESS_THAN(v: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}
func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}
let kIsIOS7: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7")
let kIsIOS7_1: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7.1")
let kIsIOS8: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("8")
let kIsIOS9: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("9")

How to tell if Cocoa Touch device can make calls? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
iOS - Detecting whether or not device support phone calls?
I'm writing an iPhone application that provides a button to call a phone number. I'm using code like the following to dial the number using a tel: URL in the usual way:
NSURL* contactTelURL = [NSURL
URLWithString:[NSString
stringWithFormat:#"tel:%#",
contactTel]];
[[UIApplication sharedApplication] openURL:contactTelURL];
It works fine on a real iPhone, but I just get an 'Unsupported URL' alert in the simulator. Presumably that would also happen on an iPod Touch, though I haven't tested that. It would be nice to remove the button when running on a device that won't make calls.
Is there a way to detect programatically whether a Cocoa Touch device can make phone calls?
From Noah Witherspoon at Make a call from my iPhone application
the simulator doesn't support a lot of iOS's URL schemes, including those for the Phone, Maps, Youtube, and SMS apps. This is also the case for devices like the iPod touch and the iPad, which don't have phone capabilities; before using any URL scheme via -openURL:, you should check for support for that scheme using -canOpenURL:, which will return YES or NO depending on whether the current device supports the URL scheme you're using
So query [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"tel://"]]
to find out if the device can make calls.
From iphonedevelopment.blogspot.com
#import <sys/utsname.h>
enum {
MODEL_IPHONE_SIMULATOR,
MODEL_IPOD_TOUCH,
MODEL_IPHONE,
MODEL_IPHONE_3G
};
#interface DeviceDetection : NSObject
+ (uint) detectDevice;
+ (NSString *) returnDeviceName:(BOOL)ignoreSimulator;
#end
#implementation DeviceDetection
+ (uint) detectDevice {
NSString *model= [[UIDevice currentDevice] model];
// Some iPod Touch return "iPod Touch", others just "iPod"
NSString *iPodTouch = #"iPod Touch";
NSString *iPodTouchLowerCase = #"iPod touch";
NSString *iPodTouchShort = #"iPod";
NSString *iPhoneSimulator = #"iPhone Simulator";
uint detected;
if ([model compare:iPhoneSimulator] == NSOrderedSame) {
// iPhone simulator
detected = MODEL_IPHONE_SIMULATOR;
} else if ([model compare:iPodTouch] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else if ([model compare:iPodTouchLowerCase] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else if ([model compare:iPodTouchShort] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else {
// Could be an iPhone V1 or iPhone 3G (model should be "iPhone")
struct utsname u;
// u.machine could be "i386" for the simulator, "iPod1,1" on iPod Touch, "iPhone1,1" on iPhone V1 & "iPhone1,2" on iPhone3G
uname(&u);
if (!strcmp(u.machine, "iPhone1,1")) {
detected = MODEL_IPHONE;
} else {
detected = MODEL_IPHONE_3G;
}
}
return detected;
}
+ (NSString *) returnDeviceName:(BOOL)ignoreSimulator {
NSString *returnValue = #"Unknown";
switch ([DeviceDetection detectDevice]) {
case MODEL_IPHONE_SIMULATOR:
if (ignoreSimulator) {
returnValue = #"iPhone 3G";
} else {
returnValue = #"iPhone Simulator";
}
break;
case MODEL_IPOD_TOUCH:
returnValue = #"iPod Touch";
break;
case MODEL_IPHONE:
returnValue = #"iPhone";
break;
case MODEL_IPHONE_3G:
returnValue = #"iPhone 3G";
break;
default:
break;
}
return returnValue;
}
#end
Here is a simple code snippet I use to check the device model is a phone and not a simulator to make sure it can make calls.
if ([[[UIDevice currentDevice] model] rangeOfString:#"Phone"].location != NSNotFound &&
[[[UIDevice currentDevice] model] rangeOfString:#"Simulator"].location == NSNotFound ) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", number] ] ];
}
You could query [[UIDevice currentDevice] model], and check if it is an iPhone.

Resources