(A working solution based on the answers is provided at the end of this publication.)
I thought this would be a neat way to handle callbacks that need to be addressed to a specific type of alert, so I don't have a single delegate method that filters out all clicks of the alert buttons. Here is the code:
#import "LSAlertView.h" @implementation LSAlertView - (id) initWithTitle:(NSString *)title message:(NSString *)message actionBlocks:(NSArray*)_actionBlocks cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... { self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles,nil]; if (self) { self.cancelButtonIndex = 0; actionBlocks = [_actionBlocks retain]; [self show]; } return self; } - (void) dealloc { [actionBlocks release]; [super dealloc]; } - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { void (^action)(void) = [actionBlocks objectAtIndex:buttonIndex]; action(); } @end
This works fine for two buttons configured like this:
- (void) restartSearches { NSArray *actionBlocks = [NSArray arrayWithObjects: ^{NSLog(@"Cancel Button Selected");}, ^{NSLog(@"Delete Button Selected");}, nil]; alertDeletingSearches = [[LSAlertView alloc] initWithTitle:@"You Are About To Delete Your Current Searches" message:@"Select Delete to Continue" actionBlocks:actionBlocks cancelButtonTitle:@"Cancel" otherButtonTitles:@"Delete", nil]; [alertDeletingSearches release]; }
But as soon as I add some useful calls to one of the blocks, for example
- (void) restartSearches { NSArray *actionBlocks = [NSArray arrayWithObjects: ^{NSLog(@"Cancel Button Selected");}, ^{ [mapController.theMap removeAnnotations:mapController.theMap.annotations]; [dataInterface deleteDB]; [[NSNotificationCenter defaultCenter] postNotificationName:@"changeToFavorites" object:nil]; NSLog(@"Delete Button Selected"); }, nil]; alertDeletingSearches = [[LSAlertView alloc] initWithTitle:@"You Are About To Delete Your Current Searches" message:@"Select Delete to Continue" actionBlocks:actionBlocks cancelButtonTitle:@"Cancel" otherButtonTitles:@"Delete", nil]; [alertDeletingSearches release]; }
it freezes and I get an EXC_BAD_ACCESS error.
Am I doing something fundamentally wrong or is there a small mistake in my logic?
UPDATE
Handled the variational problem using the Firoze sentence below. (Follow the examples given in Numbergrinder )
- (id) initWithTitle:(NSString *)title message:(NSString *)message actionBlocks:(NSArray*)_actionBlocks cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... { self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil]; if (self) { va_list args; va_start(args, otherButtonTitles); NSString* buttonTitle; while ((buttonTitle = va_arg(args, NSString *))) { [super addButtonWithTitle:buttonTitle]; } self.cancelButtonIndex = 0; actionBlocks = [_actionBlocks retain]; [self show]; } return self; }
Here is the header file:
@interface LSAlertView : UIAlertView <UIAlertViewDelegate> { NSArray *actionBlocks; } - (id) initWithTitle:(NSString *)title message:(NSString *)message actionBlocks:(NSArray*)_actionBlocks cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...; @end