Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using 'presentPointingAtBarButtonItem:' from a UINavigationBar on a ViewController in a Tabbed app, the poptip is visible on all tabs #137

Open
funnel20 opened this issue Mar 1, 2018 · 5 comments

Comments

@funnel20
Copy link
Contributor

funnel20 commented Mar 1, 2018

Situation
The app is build as a Tabbed App, so it has an UITabBarController as root view controller.
Each Tab has it's own view controller.
On the 4th tab we have an UITableViewController with an UINavigationBar with left and right UIBarButtonItems.
We've created an IBOutlet infoButton and present the pop tip by calling presentPointingAtBarButtonItem:animated::

[_poptipForManual presentPointingAtBarButtonItem:_infoButton
                                        animated:YES];

The pop tip is correctly shown:

screen shot 2018-03-01 at 10 08 47

However, when selecting another tab via the Tab Bar, the pop tip is still visible:

screen shot 2018-03-01 at 10 09 02

Analysis
Method presentPointingAtBarButtonItem:animated: determines the container view of the UIBarButtonItem and calls presentPointingAtView:inView:animated: with it.
The problem is it uses:

UIView *containerView = targetView.window;

Where the app window is returned. This is the reason why the pop tip is visible on all tabs in a Tabbed App.

Solution
The proper container view is the superview of the parent view of the UIBarButtonItem.
The (public) parent view of an UIBarButtonItem is one of:

  • UINavigationBar
  • UIToolbar
  • UITabBar

So the first step is to search upwards in the view hierarchy to determine whether the Bar Button is located in a Navigation Bar, Tool Bar or Tab Bar.
When a Navigation Bar, Tool Bar or Tab Bar is found, return it's superview and abort the search.

When no Navigation Bar, Tool Bar or Tab Bar is found, the default strategy is to use the app window (existing situation).

Here is my updated code for this method:

- (void)presentPointingAtBarButtonItem:(UIBarButtonItem *)barButtonItem animated:(BOOL)animated {
    UIView *targetView = (UIView *)[barButtonItem performSelector:@selector(view)];
    UIView *containerView = targetView;
    
    // Search upwards in the view hierarchy to determine whether the Bar Button is located in a Navigation Bar, Tool Bar or Tab Bar:
    while (containerView != nil) {
        // Get super view:
        containerView = containerView.superview;
        
        // Check Class:
        if ([containerView isKindOfClass:[UINavigationBar class]] ||
            [containerView isKindOfClass:[UIToolbar class]] ||
            [containerView isKindOfClass:[UITabBar class]]) {
            // When a Navigation Bar, Tool Bar or Tab Bar is found, return it's superview and abort while-loop:
            containerView = containerView.superview;
            break;
        }
    }
    
    // When no Navigation Bar, Tool Bar or Tab Bar is found:
    if (nil == containerView) {
        // Get the Bar Button's window:
        containerView = targetView.window;
        
        if (nil == containerView) {
            NSLog(@"Cannot determine container view from UIBarButtonItem: %@", barButtonItem);
            self.targetObject = nil;
            return;
        }
    }

    self.targetObject = barButtonItem;

    [self presentPointingAtView:targetView
                         inView:containerView
                       animated:animated];
}

Validation
This has been tested and now the pop tip is only shown on the view controller of the specific tab, which is the intended behaviour.

An added benefit is that this also works when presenting the pop tip from a Tab Bar button (this can be added to the ReadMe).
In this case the intended behaviour is that the pop tip is always visible, no matter which tab is selected.
Because the new code uses the superview of the UITabBar, this is the case.
In this example the pop tip is always presented from the 4th tab, even if it's not the selected tab:

[_poptipForConnectedTv presentPointingAtBarButtonItem:(UIBarButtonItem *)[self.tabBarController.tabBar.items objectAtIndex:3]
                                             animated:YES]; 

screen shot 2018-03-01 at 10 32 57

screen shot 2018-03-01 at 10 33 02

@funnel20
Copy link
Contributor Author

@kleinlieu What do you think of my analysis?

@NikolayEntin
Copy link

I've got the same issue, where I have pop-up ViewControllers - tooltips for the NavigationBar in the background view still shown on top of everything.

@funnel20
Copy link
Contributor Author

funnel20 commented Jul 6, 2018

@NikolayEntin It seems this project isn't under active development anymore, as the last commit is from 7 months ago.
You can manually replace the existing code in presentPointingAtBarButtonItem:animated: by my code from above.
Does that solve your issue?

@NikolayEntin
Copy link

@funnel20, thank you, I've actually reverted the code to previous state, instead of:

    UIView *targetView = (UIView *)[barButtonItem performSelector:@selector(view)];
    UIView *containerView = targetView.window;

I use old one:

    UIView *targetView = (UIView *)[barButtonItem performSelector:@selector(view)];
    UIView *targetSuperview = [targetView superview];
    UIView *containerView = [targetSuperview superview];

But I'm still wondering for motivation of the change - it did work in the past, why change to the 'window' as container for the pop-up view? What side-effects one can expect with the old code?
Can the target view be child of something else, than referred in your 'while' loop? Did you meet it on practice?

@NikolayEntin
Copy link

@funnel20 I recognized that my code was not enough (I did it via class inheritance), as for some reason those tooltips were not dismissable on click afterwards. I applied your code to the original file and it seem to work like a charm!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants