问题
I apologize if this has been asked but I can't seem to find it anywhere. I even recreated my issue in a demo project in case any of you want to see it first-hand, although I don't know where I should post it.
I have a xibless UINavigationController based app. Some of my child ViewControllers have a button on the right side at the top that then displays a UIActionSheet. My app is designed for iPhone and iPad, so when I get ready to display the UIActionSheet I do:
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:[NSString stringWithFormat:@"%@ Menu", [self title]] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Email", @"Print", nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleDefault];
if ([actionSheet respondsToSelector:@selector(showFromBarButtonItem:animated:)])
[actionSheet showFromBarButtonItem:[[self navigationItem] rightBarButtonItem] animated:YES];
else [actionSheet showInView:[self view]];
[actionSheet release];
On iPad, I'm trying to show the UIActionSheet attached to the right bar button and on iPhone it should slide in from the bottom. All of this works beautifully.
Unfortunately, if you tap the button and show the menu on iPad, but then tap the back button on the top left side of the app, the menu doesn't dismiss. Instead UINavigationController dutifully pops back and the UIActionSheet is still there. If you try to tap something on the menu you of course get a crash. If the user would have tapped anything else on the screen instead of the Back button, the menu properly dismisses.
If you try this test on iPhone, everything works as expected. There is no issue.
My demo project has an AppDelegate and a ViewController and that's about it. The AppDelegate builds an NSDictionary of NSDictionaries just so I have a model I can recurse through to demonstrate the issue. The ViewController shows all of the keys of the dictionary and if the corresponding value is an NSDictionary, you can tap it to drill down.
回答1:
This is an interesting problem. Here's what the UIActionSheet Class Reference has to say.
On iPad, this method presents the action sheet in a popover and adds the toolbar that owns the button to the popover’s list of passthrough views. Thus, taps in the toolbar result in the action methods of the corresponding toolbar items being called. If you want the popover to be dismissed when a different toolbar item is tapped, you must implement that behavior in your action handler methods.
So when you display the action sheet, it's automatically creating a UIPopoverController and set the containing toolbar (or navigation bar) as the popover's passthrough views, allowing touch events to continue. I think the best bet is to create an instance variable for your action sheet and to force it to dismiss if it is visible in -viewWillDisappear:
.
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (self.actionSheet.window) // If action sheet is on screen, window is non-nil
[self.actionSheet dismissWithClickedButtonIndex:self.actionSheet.cancelButtonIndex animated:animated];
}
回答2:
Have you tried force-dismissing the ActionSheet on viewWillDisappear?
Try this:
// In MyViewController.m
- (void)viewWillDisappear:(BOOL)animated {
[actionSheet dismissWithClickedButtonIndex:nil animated:animated];
}
*The crash sounds like a possible EXC_BAD_ACCESS. You might be losing your pointer reference to 'actionSheet' when you change views due to your release. Might be good to hang on to a reference to actionSheet in your .h file and manage the timing of your release.
*Also see the docs for info about the dismiss message: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIActionSheet_Class/Reference/Reference.html
来源:https://stackoverflow.com/questions/8404261/ipad-crash-with-uiactionsheet-displayed-from-child-view-controller