Search code examples
iosipaduitextviewuiactionsheetuipopover

Dismiss native UIActionsheet & UIPopover in iPad


This question refers to the native iOS function of displaying actionsheets and popovers when a phone number or email is selected in a webview/textview from an iPad. In case you need a refresher, the actionsheet contains two buttons that read "Add to Contacts" and "Copy". Where the popover that I am referring to is what is displayed when the user selects the "Add to Contacts" button.

I understand that to dismiss a popover one declares:

[somePopoverController dismissPopoverAnimated:YES];

To dismiss an actionsheet, one can simply call:

[someActionSheet dismissWithClickedButtonIndex:0 animated:YES];

However, my problem is that since iOS created these actionsheets/popovers for me, I do not own them, and cannot reference them to call the dismiss methods.

The use case of why I need to do this is because my application will log the user out after a specified time of no activity. When the user is logged out these actionsheets/popovers still remain on the screen, even though I have entered a new view controller and removed the old ones.

Does anyone know of how I can reference these popovers and actionsheets that I do not own? Any advice would be greatly appreciated!


Solution

  • Well, I have found a solution to dismissing both UIActionSheets and the popover that gets created from Webviews/Textviews when detecting phone numbers/email on an iPad. The solution is basically iterating through all my views using recursion until I find the views that I want to dismiss. A lot of credit has to go to the answers I found in this post Accessing UIPopoverController for UIActionSheet on iPad.

    To remove UIActionSheets:

    BOOL IsActionOpen(UIView* aView) {
        BOOL    actionOpen = NO;
        if (aView) {
            if ([aView isKindOfClass:[UIActionSheet class]]) {
                actionOpen = YES;
                [(UIActionSheet *)aView dismissWithClickedButtonIndex:0 animated:NO];
            }
            else if (aView.subviews.count > 0) {
                for (UIView* aSubview in aView.subviews) {
                    if ( IsActionOpen( aSubview)) {
                        if ([aView isKindOfClass:[UIActionSheet class]]) {
                            actionOpen = YES;
                            [(UIActionSheet *)aView dismissWithClickedButtonIndex:0 animated:NO];
                        }break;
                    }
                }
            }
        }
        return actionOpen;
    }
    
    - (void) removeActionSheetIfShowing {
        BOOL    actionOpen = NO;
        for (UIWindow* w in [UIApplication sharedApplication].windows) {
            actionOpen =  IsActionOpen(w);
            if (actionOpen)
                break;
        }
    }
    

    To remove the popover that is created when selecting "Add to Contacts" button from the generated UIActionSheet:

    BOOL IsPopOverOpen(UIView* aView) {
        BOOL    popOverOpen = NO;
        if (aView) {
            //popover is a popoverview, not a popovercontroller. We find it by checking if UIPopoverBackgroundView exists
            if([aView isKindOfClass:[UIPopoverBackgroundView class]]){
                popOverOpen = YES;
                [aView.superview removeFromSuperview];
            }
            else if (aView.subviews.count > 0) {
                for (UIView* aSubview in aView.subviews) {
                    if ( IsPopOverOpen( aSubview)) {
                        if([aView isKindOfClass:[UIPopoverBackgroundView class]]){
                            popOverOpen = YES;
                            [aView.superview removeFromSuperview];
                        }break;
                    }
                }
            }
        }
        return popOverOpen;
    }
    
    - (void) removePopOverIfShowing {
        BOOL    popOverOpen = NO;
        for (UIWindow* w in [UIApplication sharedApplication].windows) {
            popOverOpen =  IsPopOverOpen(w);
            if (popOverOpen)
                break;
        }
    }