An enhancement for UIAlertView

February 19th, 2010 by Jeff

I like objective-c protocols, and I am a fan of the interface oriented designs that it allows for. But, sometimes the indirection of using a selector with a defined signature just works better, and the problem is that UIAlertView does not take a selector. Instead, UIAlertView defines a protocol, UIAlertViewDelegate, that the alert’s delegate adopts to receive notification of the user intent. To be fair, UIAlertView communicates a bit more information back to it’s delegate than the target of an NSAlert, and the UIAlertViewDelegate protocol does a fine job achieving that goal. 99% of the time, however, I want to show an alert and have it call my named selector when it is done. To that end, I finally busted out the admittedly tiny class that does the job.

Now in my client code I show an alert like this:


RSAlert* alert =
    [[RSAlert alloc] initWithTitle: @"Title"
                           message: @"Message!"
                            target: self
                          selector: @selector(dismissedAlert:buttonIndex:)
                 cancelButtonTitle: @"OK"
                 otherButtonTitles: nil];

and handle the result with a selector, similar to NSAlert:


- (void) dismissedAlert: (RSAlert*) alert buttonIndex: (NSInteger) buttonIndex
{
    NSLog(@"dismissedStartupAlert with buttonIndex: %d", buttonIndex);
   
    [alert autorelease];
}

I realize this is an infinitesimally small annoyance, but sometimes it’s the little things that keep us happy.

RSAlert.h


#import

@interface RSAlert : NSObject
{
    UIAlertView*    alertView_;
    id              target_;
    SEL             selector_;
}

- (id)initWithTitle: (NSString*) title
            message: (NSString*) message
             target: (id) target
           selector: (SEL) selector
  cancelButtonTitle: (NSString*) cancelButtonTitle
  otherButtonTitles: (NSString*) otherButtonTitles, ...;

- (void) show;

@end

RSAlert.m


#import "RSAlert.h"

@implementation RSAlert

- (id)initWithTitle: (NSString*) title
            message: (NSString*) message
             target: (id) target
           selector: (SEL) selector
  cancelButtonTitle: (NSString*) cancelButtonTitle
  otherButtonTitles: (NSString*) otherButtonTitles, ...;
{
    self = [super init];
   
    if ( self )
    {
        target_     = [target retain];
        selector_   = selector;
        alertView_  = [[UIAlertView alloc] initWithTitle: title
                                                 message: message
                                                delegate: self
                                       cancelButtonTitle: cancelButtonTitle
                                       otherButtonTitles: nil];
   
        if ( otherButtonTitles )
        {
            va_list argList;
            id anArg;
           
            [alertView_ addButtonWithTitle: otherButtonTitles];
           
            va_start(argList, otherButtonTitles);
           
            while ( anArg = va_arg(argList, id) )
            {
                [alertView_ addButtonWithTitle: anArg];
            }
           
            va_end(argList);
        }
    }
   
    return self;
}

- (void) dealloc
{
    [target_ release];
    [alertView_ release];
    [super dealloc];
}

- (void) show
{
    [alertView_ show];
}

- (void)       alertView: (UIAlertView*) alertView
    clickedButtonAtIndex: (NSInteger) buttonIndex
{
    // Do nothing
}

- (void) alertViewCancel: (UIAlertView*) alertView
{  
    [target_ performSelector: selector_
                  withObject: self
                  withObject: (id) 0];
}

- (void) willPresentAlertView: (UIAlertView*) alertView
{
    // Do nothing
}

- (void)didPresentAlertView: (UIAlertView*) alertView
{
    // Do nothing
}

- (void)             alertView: (UIAlertView*) alertView
    willDismissWithButtonIndex: (NSInteger) buttonIndex
{
    // Do nothing
}

- (void)            alertView: (UIAlertView*) alertView
    didDismissWithButtonIndex: (NSInteger) buttonIndex
{
    [target_ performSelector: selector_
                  withObject: self
                  withObject: (id) buttonIndex];
}

@end

Comments are closed.