alert

UIAlertView with blocks (Callback functions)

UIAlertView with blocks


In this tutorial I will talk about using UIAlertView with blocks in iOS and configure it for ARC and non-ARC projects.

For sure all iOS developers have their hands dirty with UIAlertView to display dialogs to user and to make sure of dangerous actions like deletion. When I was working in an app in iOS, there was a ViewController that contains many operations and I had to display 3 AlertViews!

The problem was when I wanted to handle AlertView actions, the trivial way is to set the delegate and handle

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    int tag = alertView.tag;
    //Check for tag
}

Also I had to set tag for each Alert and check for it in delegate methods. This is the only solution and works fine, but I think its too boring. So I thought for something new to be done to handle this, I came across with using blocks and make completion handler to handle onButtonClicked.

To do this We will subclass the UIAlertView like this:

typedef void (^HGAlerViewCompletionHandler)(id alertView, int buttonIndex);

@interface HGAlertView : UIAlertView <UIAlertViewDelegate>

-(id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitlesArr:(NSArray *)otherButtonTitles;

-(void)showWithCompltionHandler:(HGAlerViewCompletionHandler)handler;

@end

as you see, I have added a similar selector  for the initWithTitle to get the otherButtons array because the original initWithTitle cause errors with me when I wanted to override it. I added new function to showWithCompletionHandler, so to fire this handler we have to know when the alert buttons clicked?, to know that I will set the delegate of AlertView to self,  we will add the next code to HGAlertView.m:

-(id)init
{
    self  = [super init];
    if (self) {
        self.delegate = self;
    }

    return self;
}

-(id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitlesArr:(NSArray *)otherButtonTitles
{
    self = [super initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles: nil];
    for (NSString *title in otherButtonTitles) {
        if ([title isKindOfClass:[NSString class]]) {
            [self addButtonWithTitle:title];
        }
    }
    if (self) {
        self.delegate = self;
    }
    return self;
}

and to implement showWithHandler function , we will write this:

-(void)showWithCompltionHandler:(HGAlerViewCompletionHandler)handler
{
    self.handler = handler;
    [super show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if(self.handler != NULL)
        self.handler(self, buttonIndex);
}

 

Now everything is Ok, to use this class you will do something like this:

HGAlertView *alert = [[HGAlertView alloc] initWithTitle:@”Warning” message:@”Are you sure to delete this post?” delegate:nil cancelButtonTitle:@”NO” otherButtonTitles:@”YES”, nil]; [alert showWithCompltionHandler:^(id alertView, int buttonIndex) { NSLog(@”button clicked at index %d”, buttonIndex); }];

You can check the whole source code at Github Project