Question

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!

Was it helpful?

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;
    }
}

OTHER TIPS

All you need is to keep a reference to them in your view controller. When you create the UIActionSheet, for example, just store it in a property of type UIActionSheet

@property (strong, nonatomic) UIActionSheet *myActionSheet;

Then, when you actually create the actionsheet, you do

self.myActionSheet = [[UIActionSheet alloc] initWithTitle:myTitle 
                                                 delegate:self 
                                        cancelButtonTitle:cancelButtonTitle 
                                   destructiveButtonTitle:destButtonTitle 
                                        otherButtonTitles:otherButtonTitle, nil];

[self.myActionSheet showFromBarButtonItem:sender animated:YES];

And when you need to dismiss it you simply do

[self.myActionSheet dismissWithClickedButtonIndex:0 animated:YES];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top