Skip to content
This repository

presentPopoverFromBarButtonItem: not working properly in iOS5 #26

Open
Giebler opened this Issue November 15, 2011 · 8 comments

6 participants

Giebler Max Fraser Chris Ballinger Vladimir Grichina Lance Parker jonathancarroll
Giebler

I traced the problem down to the frameInView code in UIBarButtonItem+WEPopover.m

First, I got an error when running due to the location of the following code:

if (!hasCustomView) {
         [self setCustomView:nil];
}

Since this code occurred before UIView *button = [parentView.subviews objectAtIndex:indexOfView]; and the newly created view was the last object in the array, the indexOfView parameter exceeded the bounds of the array.

I moved the code shown above to after the array is referenced and that eliminated the error.

However, frameInView doesn't return the proper CGRect for the button, which messes up the position of the arrow and to make matters worse, the button completely disappears from the app once pressed!

I haven't found a proper way to get the correct frame, so I ended up using presentPopoverFromRect: using two different CGRect's - one for portrait and one for landscape.

Hopefully this will save you time and effort if you plan on using presentPopoverFromBarButtonItem:

Max Fraser

Yeah, this is getting me bad - kind of a pain to present from 2 CGRect's - any update on this?

Giebler

Once I decided on the 2 CGRects, I moved on. I was working on a contract and couldn't get bogged down by this bug or I wouldn't have hit my release date.

Chris Ballinger

I have this issue as well, looks like we'll have to use a nasty CGRect workaround until someone gets around to fixing it.

Vladimir Grichina

In current build popover is presented fine initially, but bar button itself disappears after popover is shown.

Lance Parker
lancep commented May 03, 2012

I'm having the same issue...

Vladimir Grichina

I've implemented a workaround:

- (UIView *)viewForBarItem:(UIBarButtonItem *)item inToolbar:(UIToolbar *)toolbar
{
    // NOTE: This relies on internal implementation
    // TODO: Better implementation for iOS5+

    // Sort toolbar subviews to match order of toolbar items
    NSArray *subviews = [toolbar.subviews sortedArrayUsingComparator:^NSComparisonResult(id view1, id view2) {
        return [view1 frame].origin.x - [view2 frame].origin.x;
    }];

    // NOTE: Not sure why but had to filter out UIImageView from toolbar subviews
    subviews = REJECT(subviews, [obj isKindOfClass:[UIImageView class]]);

    UIView *buttonView = [subviews objectAtIndex:[toolbar.items indexOfObject:item]];
    return buttonView;
}

- (CGRect)rectForBarItem:(UIBarButtonItem *)item inToolbar:(UIToolbar *)toolbar
{
    UIView *buttonView = [self viewForBarItem:item inToolbar:toolbar];
    CGRect rect = [buttonView convertRect:buttonView.bounds toView:self.view];

    return rect;
}

You then use it like this:

 [self.sharePopover presentPopoverFromRect:[self rectForBarItem:self.shareButton inToolbar:self.rightToolbar]
                                            inView:self.view
                          permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

Note that code above depends on MACollectionUtilities. It isn't hard to rewrite without them though :)

Lance Parker
lancep commented May 10, 2012

@vgrichina thanks for the workaround, I'm still having issues, the popover shows but the arrow is in the wrong position

jonathancarroll

Made a few changes to the workaround by @vgrichina

The popover would appear in the wrong place if you had any flexible space bar button items in your toolbar because they don't have a view. You can use my code below, just be sure to set the tag on any flexible/fixed space bar button items to -1. I also removed the dependency on MACollectionUtilities.

- (UIView *)viewForBarItem:(UIBarButtonItem *)item inToolbar:(UIToolbar *)toolbar
{
    // NOTE: This relies on internal implementation
    // TODO: Better implementation for iOS5+

    // Sort toolbar subviews to match order of toolbar items
    NSArray *subviews = [toolbar.subviews sortedArrayUsingComparator:^NSComparisonResult(id view1, id view2) {
        return [view1 frame].origin.x - [view2 frame].origin.x;
    }];

    // NOTE: Not sure why but had to filter out UIImageView from toolbar subviews
    NSMutableArray *mutableSubviews = [[NSMutableArray alloc] init];
    for(UIView *subview in subviews) {
        if(![subview isKindOfClass:[UIImageView class]]) {
            [mutableSubviews addObject:subview];
        }
    }

    int itemIndex = [toolbar.items indexOfObject:item];
    int adjustedIndex = itemIndex;
    for(int i=0; i<itemIndex; i++) {
        UIBarButtonItem *anItem = [toolbar.items objectAtIndex:i];
        if(anItem.tag == -1) adjustedIndex--;
    }

    UIView *buttonView = [mutableSubviews objectAtIndex:adjustedIndex];
    [mutableSubviews release];
    return buttonView;
}

- (CGRect)rectForBarItem:(UIBarButtonItem *)item inToolbar:(UIToolbar *)toolbar
{
    UIView *buttonView = [self viewForBarItem:item inToolbar:toolbar];
    CGRect rect = [buttonView convertRect:buttonView.bounds toView:self.view];

    return rect;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.