I want to conform to the UIAlertController used in iOS 8 since UIAlertView is now deprecated. Is there a way that I can use this without breaking support for iOS 7? Is there some kind of if condition I can do to check for iOS 8 otherwise do something else for iOS 7 support?
-
FYI - Since your Deployment Target is iOS 7 (or earlier), you can just use `UIAlertView`. This will keep your code a lot simpler. – rmaddy Jun 17 '14 at 18:05
-
2I wasn't aware that Swift had a respondsToSelector... Also, the UIAlertView is screwed up in ios8, it doesn't scroll where as it does in ios 7, which is why I want to try to use both – Rocky Pulley Jun 17 '14 at 18:12
-
1The scroll doesn't work on the UIAlertController either – jcesarmobile Sep 24 '14 at 11:25
-
possible duplicate of [UIAlertView/UIAlertController iOS 7 and iOS 8 compatibility](http://stackoverflow.com/questions/25111011/uialertview-uialertcontroller-ios-7-and-ios-8-compatibility) – JAL Jun 24 '15 at 23:39
11 Answers
I think a much better way to check if a class exists (since iOS 4.2) is:
if([ClassToBeChecked class]) {
// use it
} else {
// use alternative
}
In your case, that would be:
if ([UIAlertController class]) {
// use UIAlertController
} else {
// use UIAlertView
}

- 3,733
- 30
- 25
-
I tried doing this, but when I'm running XCode 5, my code will not compile. How do I verify that this actually works on iOS7? – Huey Oct 07 '14 at 22:47
-
This should definitely work on iOs7 and Xcode5. Feel free to post your code here. Something must be wrong – Erwan Oct 15 '14 at 23:41
-
9This should be marked as correct answer. Always check for class/feature/constant/function existence instead of checking the iOS version. – Vilém Kurz Oct 22 '14 at 09:27
-
-
it might depend on whether you've got the ios 8 SDK. http://stackoverflow.com/questions/24015490/how-can-i-install-the-new-ios-sdk-on-xcode-5 – mitrenegade Oct 23 '14 at 20:28
-
1
-
@mitrenegade this approach prevents you from checking the iOS version. It will work on any iOS after 4.2 – Erwan Nov 27 '14 at 12:38
-
2Yes, but if someone is compiling code that was written by someone with the ios 8 sdk, but they are now using the ios 7 sdk on xcode 5, the code will not compile. That's the problem @huey is getting because he's compiling on xcode 5, UIAlertController will not be recognized. If you are using the most recent SDK, your answer is the correct one because when a phone running ios7 runs your app built with ios8, it will just return nil on [UIAlertController class]. – mitrenegade Nov 27 '14 at 14:58
-
@mitrenegade but if he is compiling with iOS7 on Xcode 5, the rest of the code will not compile anyway. What's the point of testing if the version allows to use this class if you compile it with a version that does not know the class – Erwan Nov 27 '14 at 15:01
-
2right, so @huey shouldn't try to compile on xcode 5. he needs to use xcode 6 and use your code to prevent calling UIAlertController if a device uses ios7. my comment was meant to point out that the reason it's not compiling is that the class is not available on the ios 7 sdk. however, your first response said that it will work on ios7 and xcode 5, which is not true if that class is not available. – mitrenegade Nov 27 '14 at 15:18
-
@huey can use Xcode 6 to build and run on iOS7 simulator to confirm his code runs on iOS7. He doesn't need Xcode5 to do that. – Erwan Nov 28 '14 at 03:18
-
My practice is to consult the Developer Library and code accordingly. For example, UIActionSheet is deprecated in favor of UIAlertController in iOS 8, but [UIActionSheet class] will return true in iOS 8. If in doubt, read the library to consult the API, and check the OS version and the existence of the class in the code for best practice (defensive programming). – Hahnemann Jun 13 '15 at 18:47
Objective C (as mentioned above)
if ([UIAlertController class]) {
// use UIAlertController
} else {
// use UIAlertView
}
Swift
if objc_getClass("UIAlertController") == nil {
// use UIAlertView
} else {
// use UIAlertController
}
Don't use if NSClassFromString("UIAlertController") == nil
It is not working because the signature for this method is func NSClassFromString(_ aClassName: String!) -> AnyClass!

- 205
- 3
- 6
Please see the answer of Erwan (below my answer) as I see it is the best.
--
You can check the iOS version to use appropriate control like this:
if (([[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] == NSOrderedAscending)) {
// use UIAlertView
}
else {
// use UIAlertController
}

- 192
- 1
- 10
-
2I have posted what I think is a better approach below, checking if the class exists rather than checking the version of the OS – Erwan Sep 04 '14 at 02:37
-
3This is a fragile way to perform this check. In fact Apple recommends against these kind of checks. The answer by Erwan is the correct answer. – squarefrog Oct 07 '14 at 10:34
-
One should never check against version numbers in code, this is very bad practice. As squarefrog points out @Erwan has the better solution, always check against capabilities/features. – SHaKie Oct 15 '14 at 09:24
-
As noted, conditional eval of [UIAlertController class] is the preferred strategy. If checking the version for the OS is necessary, the preferred convention is to compare NSFoundationVersionNumber -- detailed [here](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/SupportingEarlieriOS.html#//apple_ref/doc/uid/TP40013174-CH14-SW3) – Mark Feb 09 '15 at 14:09
As others have already mentioned - always check whether a feature exists. I believe the safest approach is following:
if (NSClassFromString(@"UIAlertController")) {
// use UIAlertController
} else {
// use UIAlertView
}
With the obvious risk of entering a class name with a typo. :)
From documentation of NClassFromString:
[Returns] The class object named by aClassName, or nil if no class by that name is currently loaded. If aClassName is nil, returns nil.
Availability iOS (2.0 and later)
-
1This code snippet translated into Swift 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. So this snippet of code is unstable and I would not recommend using it on production. – King-Wizard Mar 17 '15 at 00:19
-
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.
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.

- 15,628
- 6
- 82
- 76
-
"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." That is true. I wish I read this before. – thomasdao May 18 '15 at 10:45
// Above ios 8.0
float os_version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (os_version >= 8.000000)
{
//Use UIAlertController
}
else
{
//UIAlertView
}

- 3,585
- 2
- 24
- 42
Create simple utility function
to reduce code
CODE :
// pass minimum required iOS version
BOOL isOSSupported(NSString *minRequiredVersion)
{
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL isOSSupported = ([currSysVer compare:minRequiredVersion options:NSNumericSearch] != NSOrderedAscending) &&
![currSysVer isEqualToString:@"Unknown"];
return isOSSupported;
}
USE :
if(isOSSupported("8.0")
{
// Code for iOS8 and above
}
else
{
// Code for iOS7 and below
}
Or Use system constant
NSFoundationVersionNumber_iOS_7_1
as below
if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1)
{
// Code for iOS8 and above
}
else
{
// Code for iOS7 and below
}
for more options Link
-
1There is no need of -1 :)), who did this please share your thought to others – Jageen Sep 23 '14 at 14:44
-
Bad practice, never check against version numbers. Always check against capabilities/features. – SHaKie Oct 15 '14 at 09:27
-
@SHaKie then in which case its good to use constant NSFoundationVersionNumber_iOS_7_1 provided by apple – Jageen Oct 15 '14 at 10:36
-
The best practice is to check if the class exists as on my answer posted above. For methods you could also check that the class responds to @selector(yourMethod) – Erwan Oct 15 '14 at 23:40
-
@Jageen I'm afraid not. 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. – SHaKie Oct 19 '14 at 16:57
I have created very simple wrapper in Objective-C, that supports both - old iOS UIAlertView and new one UIAlertViewController
https://github.com/MartinPerry/UIAlert/
It also brings the new action blocks usage to old UIAlertView
Sample:
MyAlertMessage * a = [[MyAlertMessage alloc] initWithTitle:@"Hello" WithMessage:@"World"];
[a addButton:BUTTON_OK WithTitle:@"OK" WithAction:^(void *action) {
NSLog(@"Button OK at index 0 click");
}];
[a addButton:BUTTON_CANCEL WithTitle:@"Cancel" WithAction:^(void *action) {
NSLog(@"Button Cancel at index 1 click");
}];
[a show];

- 9,232
- 8
- 46
- 114
I have written one class that wrap the UIAlertView and use UIAlertController. For the programmer is transparently hence is sufficient import this classes in the project. The utility of this classes is when in a old project there are more UIAlertView to change. Link: https://github.com/kennymuse/UIAlertView

- 101
- 1
- 3
Method one
by ios system version check
#define iOSVersionLessThan(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
// below ios8 ,create UIAlertView
if(iOSVersionLessThan(@"7.0")){
// todo
// ios8 and above ,UIActionController avaliable
}else{
// todo
}
Method two
by system feature detect
// create UIActionController
if([UIActionController class]){
// todo
// create UIAlertView
}else{
// todo
}
But,there's a third lib named PSTAlertController that deal with backwards compatible to iOS 7 of UIActionSheet and UIAlertView.
ref to

- 2,809
- 2
- 21
- 31
Try below code. It works fine for both iOS 8 and below version.
if (IS_OS_8_OR_LATER) {
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
}];
[alertVC addAction:cancelAction];
[[[[[UIApplication sharedApplication] windows] objectAtIndex:0] rootViewController] presentViewController:alertVC animated:YES completion:^{
}];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[alert show];
}

- 91
- 1
- 10