patternMinor
Generic class for displaying UIAlertView / UIAlertController on iOS
Viewed 0 times
genericuialertviewiosdisplayingforclassuialertcontroller
Problem
To address backwards compatibility for
This is not something I would like to roll out in production hence I would appreciate few extra pair of eyes taking a look at it.
Here is a link to the GitHub gist.
```
//UIAlertMode.h
#import
#import
typedef void (^AlertViewSelectionBlock) (NSInteger);
typedef void (^AlertControllerDefaultAction ) (UIAlertAction *);
typedef void (^AlertControllerCancelAction) (UIAlertAction *);
typedef void (^GenericBlock) (void *);
@interface UIAlertMode : NSObject
@property (assign, nonatomic) AlertViewSelectionBlock alertViewBlock;
@property (assign, nonatomic) AlertControllerCancelAction cancelAlertAction;
@property (assign, nonatomic) AlertControllerDefaultAction defaultAlertAction;
:(NSString *) message
:(NSString *) cancelButtonTitle
:(NSString *) otherButtonTitle;
@end
// UIAlertMode.m
#import "UIAlertMode.h"
#import
#import "AppDelegate.h"
@interface UIAlertMode () {
UIAlertView *_alertView;
UIAlertController *_alertController;
}
@end
@implementation UIAlertMode
@synthesize alertViewBlock;
@synthesize defaultAlertAction;
@synthesize cancelAlertAction;
self = [super init];
return self;
}
:(NSString *) message
:(NSString *) cancelButtonTitle
:(NSString *) otherButtonTitle {
self = [super init];
if ([self supportsiOS8]) {
_alertController = [UIAlertController alertControllerWithTitle:title message:message preferred
UIAlertView, I have come up with an interface that would seem to work for both iOS versions 8 and lower.This is not something I would like to roll out in production hence I would appreciate few extra pair of eyes taking a look at it.
Here is a link to the GitHub gist.
```
//UIAlertMode.h
#import
#import
typedef void (^AlertViewSelectionBlock) (NSInteger);
typedef void (^AlertControllerDefaultAction ) (UIAlertAction *);
typedef void (^AlertControllerCancelAction) (UIAlertAction *);
typedef void (^GenericBlock) (void *);
@interface UIAlertMode : NSObject
@property (assign, nonatomic) AlertViewSelectionBlock alertViewBlock;
@property (assign, nonatomic) AlertControllerCancelAction cancelAlertAction;
@property (assign, nonatomic) AlertControllerDefaultAction defaultAlertAction;
- (id) initAlertWith:(NSString *) title
:(NSString *) message
:(NSString *) cancelButtonTitle
:(NSString *) otherButtonTitle;
- (BOOL) supportsiOS8;
- (void) showAlertFor:(AlertViewSelectionBlock) alertViewBlock;
- (void) showAlertControllerFor:(AlertControllerDefaultAction) defaultAction :(AlertControllerCancelAction) cancelAction;
- (void) showAlertWith:(GenericBlock) block;
@end
// UIAlertMode.m
#import "UIAlertMode.h"
#import
#import "AppDelegate.h"
@interface UIAlertMode () {
UIAlertView *_alertView;
UIAlertController *_alertController;
}
@end
@implementation UIAlertMode
@synthesize alertViewBlock;
@synthesize defaultAlertAction;
@synthesize cancelAlertAction;
- (id) init {
self = [super init];
return self;
}
- (id) initAlertWith:(NSString *) title
:(NSString *) message
:(NSString *) cancelButtonTitle
:(NSString *) otherButtonTitle {
self = [super init];
if ([self supportsiOS8]) {
_alertController = [UIAlertController alertControllerWithTitle:title message:message preferred
Solution
As a start, this is confusing:
There was a time when I was uncomfortable with ternary operators. They're admittedly kind of weird. I've gotten used to them, and I do enjoy them, but they should be used appropriately.
The logic here is that
For starters, I'd change this to look more like this:
Now it's slightly more readable and more clear what we're doing. We don't actually care what's returned beyond whether or not it is
However, there's still problems...
Your method is called
I can use a class called
Moreover, it's likely that
Instead, what we actually need to do is check the version of iOS that the user is actually using and compare it to the minimum iOS version for Apple's
For starters, we can use the following method to determine the device's version:
This will return the device's version as an
Now, we compare the return of this to the version we want.
- (BOOL) supportsiOS8 {
Class kAlertViewClass = NSClassFromString(@"UIAlertController");
return !kAlertViewClass ? NO : YES;
}There was a time when I was uncomfortable with ternary operators. They're admittedly kind of weird. I've gotten used to them, and I do enjoy them, but they should be used appropriately.
The logic here is that
NSClassFromString returns nil if it can't figure out what class you've specified.For starters, I'd change this to look more like this:
- (BOOL)supportsiOS8 {
return NSClassFromString(@"UIAlertController") != nil;
}Now it's slightly more readable and more clear what we're doing. We don't actually care what's returned beyond whether or not it is
nil.However, there's still problems...
Your method is called
supportsiOS8, but all your method actually checks is whether or not this class can see a class called UIAlertController. And there's a difference.I can use a class called
UIAlertController on iOS 7 and lower. It's simply a matter of me implementing that class myself. If I've imported that class's file into this file, your supportsiOS8 will return YES. And my implementation of UIAlertController may or may not match Apple's implementation. So with that said, simply renaming the method as supportsAlertController wouldn't really work.Moreover, it's likely that
UIAlertController will continue to exist in iOS 9 and onward. Apps that use this class may or may not actually support iOS 8 (because supporting iOS 8 isn't actually necessary).Instead, what we actually need to do is check the version of iOS that the user is actually using and compare it to the minimum iOS version for Apple's
UIAlertController (iOS 8).For starters, we can use the following method to determine the device's version:
[[UIDevice currentDevice] systemVersion];This will return the device's version as an
NSString. It might look something like @"8.1".Now, we compare the return of this to the version we want.
- (BOOL)hasMinimumRequiredOS {
NSString *deviceVersion = [[UIDevice currentDevice] systemVersion];
return ([deviceVersion compare:@"8" options:NSNumericSearch] != NSOrderedAscending);
}Code Snippets
- (BOOL) supportsiOS8 {
Class kAlertViewClass = NSClassFromString(@"UIAlertController");
return !kAlertViewClass ? NO : YES;
}- (BOOL)supportsiOS8 {
return NSClassFromString(@"UIAlertController") != nil;
}[[UIDevice currentDevice] systemVersion];- (BOOL)hasMinimumRequiredOS {
NSString *deviceVersion = [[UIDevice currentDevice] systemVersion];
return ([deviceVersion compare:@"8" options:NSNumericSearch] != NSOrderedAscending);
}Context
StackExchange Code Review Q#67378, answer score: 3
Revisions (0)
No revisions yet.