I have discovered a strange problem when using UIActionSheet on the iPhone (iOS 4.2). Consider this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:@"TestSheet"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles: nil];
[actionSheet addButtonWithTitle:@"one"];
[actionSheet addButtonWithTitle:@"two"];
[actionSheet addButtonWithTitle:@"three"];
[actionSheet addButtonWithTitle:@"four"];
[actionSheet addButtonWithTitle:@"five"];
[actionSheet addButtonWithTitle:@"six"];
//uncomment next line to see the problem in action
//[actionSheet addButtonWithTitle:@"seven"];
[actionSheet showInView:window];
[actionSheet release];
return YES;
}
- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(@"buttonIndex: %d, cancelButtonIndex: %d, firstOtherButtonIndex: %d",
buttonIndex,
actionSheet.cancelButtonIndex,
actionSheet.firstOtherButtonIndex);
}
If you start this application, the actionsheet behaves as expected. That means the cancelButtonIndex is always 0, and the button indexes are reported correctly. 1 for button "one" and so on. If you comment in the line for adding the seventh button, the actionsheet produces a sort of tableview, with the cancel button on an extra line. If I press the "one" button in this case, the buttonindex variable is 0, but so is the cancelButtonIndex. It is impossible to tell if the user has tapped the "cancel" or the "one" button. That doesn't seem like it should be this way. Does anyone disagree? Thanks for your help.
I ran into the same issue even though I already was including the Cancel Button as the last one in the action sheet and setting its index accordingly. My problems had to do with the 'Destructive' button. After some investigation, here is my take on the problem:
After N buttons have been added to the actionsheet, it switches its layout to put the Destructive button at the top and the Cancel button at the bottom. In between is a scrollable view that includes all of the other buttons. Other sources indicate that this is a a table view.
N is 7 for Portrait orientation and 5 for Landscape orientation. N is 9 for Portrait orientation on larger, 4" screen. These numbers are for all buttons including Cancel and Destructive. To be clear, N is the largest number of buttons before the switch. N+1 buttons causes the UIActionSheet to switch to the scrollable view.
It does not matter where in the action sheet you had originally put the Cancel and Destructive buttons within the action sheet. Once the limit has been reached, the Destructive button is moved to the top and the Cancel is moved to the bottom.
The problem is that the indices are not adjusted accordingly. So, if you did not initially add the Cancel as the last button and the Destructive as the first, the wrong index will be reported in actionSheet:clickedButtonAtIndex: as the initial report stated.
So, if you are going to have more than N buttons in your action sheet you MUST add the Destructive button to the actionSheet as the first button to the action sheet. You MUST add the Cancel button as the last button added to the action sheet. When initially constructing the sheet just leave both as nil, as described in another answer.