views:

583

answers:

4

I have a requirement in an application where I need to be able to add otherButtonTitles dynamically, dependent upon some BOOL switches that a user has specified in the settings. However, I can't seem to figure out how to go about doing this in the UIActionSheet initialization. I've tried to pass a NSString array (NSString[2]), and also a NSArray without any luck.

Any help here is greatly appreciated.

+4  A: 

You can add new buttons to the (already initialized) UIActionSheet with addButtonWithTitle: method. You can also create your custom UIButtons and add them to UIActionSheet's view as a subViews

Vladimir
I had been using `addButtonWithTitle:`, then adding a "Cancel" button as the last one, using `setCancelButtonIndex` to identify it. The problem is when you have more buttons than will fit on the screen, it switches to a UITableView, and the buttons become cells in the table. If you don't have an actual Cancel button specified via `cancelButtonTitle`, there's no way to close the sheet because no button appears. You have to exit the app at that point.See these screens for an example:http://conceptcache.com/tmp/with_cancel_button.pnghttp://conceptcache.com/tmp/without_cancel_button.png
harrywynn
That's strange - I've just created UIActionSheet with 20 buttons (added all of them with attButtonTitle: call). The sheet dismisses ok and both didDismissWithButtonIndex: and clickedButtonAtIndex: delegate methods get called... What version of sdk are you using?
Vladimir
A: 

If you need that many buttons, create your own modal view and your own delegate protocol.

Check the documentation for presentModalViewController:animated and dismissModalViewController:animated:

When the user dismisses your modal view, your delegate can receive a method you build, something like customActionSheetDidFinish:(int)buttonChosen

Rob
+1  A: 

I ended up solving this by using some nil strings and an array. I place the dynamic titles I need in an array, then loop through it and set the placeholder strings with as many titles as necessary. The placeholder strings are then passed to otherButtonTitles: in the action sheet initialization. Being otherButtonTitles: is terminated by nil, you can pass as many placeholder strings as necessary, as the first nil placeholder will terminate the rest.

// button titles    
NSMutableArray *buttons = [[NSMutableArray alloc] init];
[buttons addObject:@"Button 1"];
[buttons addObject:@"Button 2"];

// placeholders
NSString *button0 = nil, *button1 = nil, *button2 = nil;

// put together the buttons
for (int x = 0; x < buttons.count; x++) {
    switch (x) {
     case 0:
      button0 = [buttons objectAtIndex:x];
      break;
     case 1:
      button1 = [buttons objectAtIndex:x];
      break;
     case 2:
      button2 = [buttons objectAtIndex:x];
      break;
    }
}

// action sheet
UIActionSheet *option = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:button0, button1, button2, nil];

Hope this is helpful to others facing a similar dilemma.

harrywynn
And what would you do if you need 20 or 30 buttons?
Vladimir
Well, I only need a max of 5, so this works for this particular application. This probably wouldn't be practical if you needed 20 or 30.
harrywynn
+1  A: 

The easiest way to do this that I have found is initially create your action sheet with no buttons, including no cancel or destructive button:

UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:@"Dynamic"
                                                        delegate:self
                                               cancelButtonTitle:nil
                                          destructiveButtonTitle:nil
                                               otherButtonTitles:nil];

Then add a load of buttons as needed:

if(buttonX)
{
    [actionSheet addButtonWithTitle:@"Button X"];
}
if(buttonY)
{
    [actionSheet addButtonWithTitle:@"Button Y"];
}
if(buttonZ)
{
    [actionSheet addButtonWithTitle:@"Button Z"];
}

Then finally add the cancel button at the end and set the cancel button index:

[actionSheet addButtonWithTitle:@"Cancel"];
actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;

Of course you can add both a cancel button and/or a destructive button in this way.

jhabbott