Skip to content

Instantly share code, notes, and snippets.

@isutton
Created July 19, 2012 21:11
Show Gist options
  • Save isutton/3146844 to your computer and use it in GitHub Desktop.
Save isutton/3146844 to your computer and use it in GitHub Desktop.
Alert Pattern for Cocoa Touch
typedef enum {
LoginHandlerConnectionError,
LoginHandlerInvalidCredentialsError,
LoginHandlerUnknownError
} LoginHandlerError;
typedef enum {
LoginHandlerDismissAction,
LoginHandlerRetryAction
} LoginHandlerAction;
typedef void (^LoginHandlerBlock)();
typedef void (^LoginHandlerFailureBlock)(LoginHandlerError error, LoginHandlerAction action);
@interface LoginHandler : <UIAlertViewDelegate>
@property (nonatomic, copy) LoginHandlerBlock successBlock;
@property (nonatomic, copy) LoginHandlerBlock completionBlock;
@property (nonatomic, copy) LoginHandlerFailureBlock failureBlock;
- (void)loginWithEmail:(NSString *)email password:(NSString *)password;
@end
#import "LoginHandler.h"
@implementation LoginHandler {
LoginHandlerError _error;
}
@synthesize successBlock = _successBlock;
@synthesize completionBlock = _completionBlock;
@synchronized failureBlock = _failureBlock;
- (void)loginWithEmail:(NSString *)email password:(NSString *)password
{
// Any email address containing "@me.com" triggers successBlock. Any email
// address containing "@example.com" triggers an invalid credential error. Any
// other email address trigger unknown error.
if ([email rangeOfString:@"@me.com"].location != NSNotFound) {
if (_successBlock)
_successBlock();
if (_completionBlock)
_completionBlock();
return;
}
else if ([email rangeOfString:@"@example.com"].location != NSNotFound) {
_error = LoginHandlerInvalidCredentialsError;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Invalid Credentials"
message:@"The credentials you provided are invalid."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
else {
_error = LoginHandlerConnectionError;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Connection Error"
message:@"A connection could not be made to the server."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"Retry", @"Cancel", nil];
[alertView show];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//
// Here we have three possible outcomes:
//
// 1. Provided credentials are invalid and user wants to dismiss the alert to
// change the credentials.
//
// 2. There was a connection problem, and the user wants to retry the communication
// with the remote service.
//
// 3. There was a connection problem, and the user wants to dismiss the alert.
//
LoginHandlerAction action = LoginHandlerDismissAction;
if (_error == LoginHandlerConnectionError && buttonIndex == 0) {
action = LoginHandlerRetryAction ;
}
if (_failureBlock)
_failureBlock(_error, action);
if (_completionBlock)
_completionBlock();
}
@end
@interface LoginViewController : UIViewController
- (IBAction)loginButtonTapped:(id)sender;
@end
#import "LoginViewController.h"
#import "LoginHandler.h"
@implementation LoginViewController
- (void)viewDidLoad
{
UIButton *button = [UIButton buttinWithType:UIButtonTypeRoundedRect];
button.frame = CGRectZero;
[button addTarget:self action:@selector(loginButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (IBAction)loginButtonTapped:(id)sender
{
LoginHandler *loginHandler = [[LoginHandler alloc] init];
__block LoginViewController *blockSelf = self;
loginHandler.failureBlock = ^(LoginHandlerError error, LoginHandlerAction action) {
switch (action) {
case LoginHandlerRetryAction:
[blockSelf loginButtonTapped:nil];
break;
}
};
[loginHandler loginWithEmail:@"foo@me.com" password:@"aPassword"];
}
@end
@sgoodwin
Copy link

This is good except you don't want to hardcode the button index check. If you just want to know if the button wasn't the cancel button, you can compare buttonIndex against [alertView cancelButtonIndex]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment