presentPopoverFromBarButtonItem: not working properly in iOS5 #26

Closed
Giebler opened this Issue Nov 15, 2011 · 8 comments

Comments

Projects
None yet
7 participants
@Giebler

Giebler commented Nov 15, 2011

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:

@alivemedia

This comment has been minimized.

Show comment
Hide comment
@alivemedia

alivemedia Jan 18, 2012

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

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

@Giebler

This comment has been minimized.

Show comment
Hide comment
@Giebler

Giebler Jan 18, 2012

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.

Giebler commented Jan 18, 2012

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.

@chrisballinger

This comment has been minimized.

Show comment
Hide comment
@chrisballinger

chrisballinger Mar 12, 2012

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

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

@vgrichina

This comment has been minimized.

Show comment
Hide comment
@vgrichina

vgrichina Apr 4, 2012

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

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

@lancep

This comment has been minimized.

Show comment
Hide comment
@lancep

lancep May 3, 2012

I'm having the same issue...

lancep commented May 3, 2012

I'm having the same issue...

@vgrichina

This comment has been minimized.

Show comment
Hide comment
@vgrichina

vgrichina May 9, 2012

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 :)

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 :)

@lancep

This comment has been minimized.

Show comment
Hide comment
@lancep

lancep May 10, 2012

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

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

This comment has been minimized.

Show comment
Hide comment
@jonathancarroll

jonathancarroll Aug 3, 2012

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

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

@werner77 werner77 closed this Nov 20, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment