UIActionSheet in iOS7 dismissing when user taps AN

2019-05-01 10:30发布

问题:

I've noticed that in iOS 7 a **UIActionSheet** automatically dismisses when a user taps anywhere on the screen on an **iPhone**. This was NOT the case in iOS 6 and is leading to unintended effects. Is this a UI change? Bug? Is there a way to disable this?

From iOS 7 docs:
"As described in iOS human interface guidelines, you should include a Cancel button with action sheets displayed on iPhone and with those displayed on iPad over an open popover. Otherwise on iPad, action sheets are displayed within a popover, and the user can cancel the action sheet by tapping outside the popover, in which case you do not need to include a Cancel button."

This seems to suggest that the behavior of dismissing when tapping anywhere outside the action sheet should only pertain to iPads. But this is now happening on an iPhone running iOS 7 when it doesn't on an iPhone running iOS 6

回答1:

Regarding your question Is this a UI change? Bug?

It is seems like an UI change not a bug how can I say that ?
Have a look at the image i took from iOS7 simulator
It is a image of Maps application of iPhone.


When you click on button ( display in red rectangle ) one action sheet will display which have Cancel button like below

And if you click any where else it will close, same behaviour also found in other Apple applications also like safari.
Regarding your question Is there a way to disable this?
Sorry but i don't have answer for that.



回答2:

A word before I post my solution. It is very easy to fear a minor change in behavior and to want to disable it right away. But consider first consistency. This is how action sheets behave across the operating system. If you disable this behavior, you will break consistency and this will result in a subpar experience for your users.

That said, here is my solution.


UIActionSheet on iPhone opens its view in a separate UIWindow instance which becomes key when it is shown. You can access this window using [UIApplication sharedApplication].keyWindow. If you inspect the view hierarchy of this window, you will notice several private classes such as dimming view. You can recursively traverse this view hierarchy and set view.userInteractionEnabled = NO; to every view there that is not a subclass of UIButton. This should do the trick.



回答3:

As @nvrtdfrst implies in his comments, setting cancelButton: nil will get rid of the default dismissal behavior. But you can still have a cancel button by setting the text for one of the custom buttons to @"Cancel"--to be treated by the delegate method, something like this:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
     if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:@"Cancel"]) {
         // your cancellation code here
     }
}

A bit hacky, but that's a simple solution.

H/T: null.



回答4:

Use

- (void)actionSheet:(UIActionSheet *)actionSheet 
didDismissWithButtonIndex:(NSInteger)buttonIndex {...}


回答5:

This worked for me.

    (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex == 0) {
        [self performSegueWithIdentifier:@"firstOption" sender:self];
    }else if (buttonIndex == 1){
        [self performSegueWithIdentifier:@"secondOption" sender:self];
    } else if (buttonIndex != 0 || buttonIndex != 1) {
        [actionSheet cancelButtonIndex];
    }

}