Dynamic UIActionSheet

Some actions may sometimes have more than one possible target, and other times only one.

For example: Calling a contact. If the contact has just one phone number, you openURL with it and you’re done. But if she has several numbers, you want to open a UIActionSheet to let the user choose which number to call.

Or picking an image. If you’re running on a camera-less iPod, you just show a UIImagePickerController to pick from the photo library. But with a camera, and maybe an existing image to delete, you’ll want to show an action sheet to choose the actual action that your “Photo” button performs.

So you need to do two things:

  1. Decide whether to show an action sheet at all or just do the one possible action.
  2. If you need an action sheet, fill it dynamically with the possible targets for action.

The code to do that doesn’t have to be complicated. It can actually be as simple as this:

@interface MyViewController() :  {
	NSArray *possibleTargets; // action sheet buttons go here
}
@end

@implementation MyViewControllerMyViewController

- (IBAction)selectTargetForAction:(id)sender
{
    possibleTargets = SomeWayToFindPossibleTargets();

    if ([possibleTargets count] == 1) {
        // just call the one number, or show the one image picker
        [self doAction:[possibleTargets lastObject]];
    }
    else if ([possibleTargets count] > 1) {
        // show a dynamically filled action sheet
        UIActionSheet *targetsSheet =
            [[UIActionSheet alloc] initWithTitle:__(@"Select")
                delegate:self
                cancelButtonTitle:nil // since we want it last
                destructiveButtonTitle:nil
                otherButtonTitles:nil]; // since we can't hard-code them
        for (NSString *target in possibleTargets) {
            [targetsSheet addButtonWithTitle:__(target.title)];
        }
        targetsSheet.cancelButtonIndex = [targetsSheet addButtonWithTitle:__(@"Cancel")];
        [targetsSheet showInView:self.view];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != actionSheet.cancelButtonIndex) {
        [self doAction:[possibleTargets objectAtIndex:buttonIndex]];
    }
}

@end

Notes:

  1. The @interface code above is part of the .m file, as described in my earlier post How to Keep Your Protocols Private.
  2. If you’re puzzled by the meaning of __(@"String") then see my earlier post on How To Make NSLocalizedString Fun To Use.
  3. The objects in possibleTargets can hold a selector (SEL) of the actual method to be executed, or they can hold just relevant data for the action (like a phone number to call).

Leave a Reply