UIBarButtonItem with UIButton as CustomView - from UIButton, how to access UIBarButtonItem?

I have a UIBarButtonItem with UIButton as a custom view.

UIButton has addTarget:action: . In action, I present a popover. I am presenting now from sender.frame ( UIButton Frame), which I want to present from UIBarButtonItem .

How can I access UIBarButtonItem from UIButton ?

+6
source share
5 answers

If you set UIButton as a customView for a UIBarButtonItem or a child of a custom view, you can pick up the view hierarchy from your button until you find the UIToolbar or UINavigationBar that contains the button, then search for panel items for those whose user view is the button (or ancestor buttons).

Here is my completely untested code for this. You must call [[self class] barButtonItemForView:myButton] to get the element containing your button.

 + (BOOL)ifBarButtonItem:(UIBarButtonItem *)item containsView:(UIView *)view storeItem:(UIBarButtonItem **)outItem { UIView *customView = item.customView; if (customView && [view isDescendantOfView:customView]) { *outItem = item; return YES; } else { return NO; } } + (BOOL)searchBarButtonItems:(NSArray *)items forView:(UIView *)view storeItem:(UIBarButtonItem **)outItem { for (UIBarButtonItem *item in items) { if ([self ifBarButtonItem:item containsView:view storeItem:outItem]) return YES; } return NO; } + (UIBarButtonItem *)barButtonItemForView:(UIView *)view { id bar = view; while (bar && !([bar isKindOfClass:[UIToolbar class]] || [bar isKindOfClass:[UINavigationBar class]])) { bar = [bar superview]; } if (!bar) return nil; UIBarButtonItem *item = nil; if ([bar isKindOfClass:[UIToolbar class]]) { [self searchBarButtonItems:[bar items] forView:view storeItem:&item]; } else { UINavigationItem *navItem = [bar topItem]; if (!navItem) return nil; [self ifBarButtonItem:navItem.backBarButtonItem containsView:view storeItem:&item] || [self ifBarButtonItem:navItem.leftBarButtonItem containsView:view storeItem:&item] || [self ifBarButtonItem:navItem.rightBarButtonItem containsView:view storeItem:&item] || ([navItem respondsToSelector:@selector(leftBarButtonItems)] && [self searchBarButtonItems:[(id)navItem leftBarButtonItems] forView:view storeItem:&item]) || ([navItem respondsToSelector:@selector(rightBarButtonItems)] && [self searchBarButtonItems:[(id)navItem rightBarButtonItems] forView:view storeItem:&item]); } return item; } 
+9
source

First of all, why do you need to access the UIBarButtonItem ?

Then, to create a UIBarButtonItem with a custom view, I suggest you create a category extension similar to the following (in this case, the user view is UIButton ).

 //UIBarButtonItem+Extension.h + (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action; //UIBarButtonItem+Extension.m + (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height); button.titleLabel.textAlignment = UITextAlignmentCenter; [button setBackgroundImage:image forState:UIControlStateNormal]; [button setTitle:title forState:UIControlStateNormal]; [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; return [barButtonItem autorelease]; } 

and use it like this (first import of UIBarButtonItem+Extension.h ):

 UIBarButtonItem* backBarButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"YoutImageName"] title:@"YourTitle" target:self action:@selector(doSomething:)]; 

where the selector is a method implemented inside the class (target) that uses this panel element.

Now in the doSomething: selector doSomething: you can do the following:

 - (void)doSomething:(id)sender UIButton* senderButton = (UIButton*)sender; [popover presentPopoverFromRect:senderButton.bounds inView:senderButton...]; } 

The category in this case is useful not to duplicate the code. Hope this helps.

PS I do not use ARC, but the same considerations can be applied.

Edit:

An easy solution to access a panel item might be the following:

  • Subclass a UIButton
  • Create a property of type UIBarButtonItem (weak to avoid saving the loop)
  • Insert the panel button element into the UIButton when creating it.

Maybe this might work, but I prefer the first.

+6
source

Not sure if you need UIButton. If what you are doing is submitting an action or even customizing a button with an image, you need UIBarButtonItem .

If you want to capture a frame from UIButton in order to achieve a presentation, I think you'd better just evaluate the position of the UIBarButtonItem . This should not be too complicated, especially if it is one or the other of your UINavigationItem leftBarButtonItem or rightBarButtonItem .

I usually use the KISS (Keep It Simple, Stupid!) Rule. Even Apple does this ... when starting an application from Springboard, the application always expands from the center of the screen, and not from the application icon.

Just an offer.

EDIT

OK, I just read the UIPopoverController link (I never used it). I think you want presentPopoverFromBarButtonItem:permittedArrowDirections:animated: and pass your BBI as the first parameter. The reason this method exists is to solve your problem - BBIs do not have a frame because they are not subclasses of NSView. Apple knows that you want to do this, and provides this method. In addition, I think that if you use this method, your autorotation will also work. Maybe I'm wrong, give him a chance.

As for your customized layout, I think that if you play it in a UIView and configure BBI with this, you will do better. This, of course, is up to you.

In any case, you get a link to the BBI, either by connecting it as an IBOutlet with your NIB, or by storing the link to it when you create it in code. Then just pass this link to the popover method described above. I think this might work for you.

Moar

BBI is just a member of your class - iVar with a strong reference property on it, possibly related as an IBOutlet to your NIB. Then you can access it from any method you want in the class.

Example: (not sure if I am managing popover controller memory correctly)

 @interface MyViewController : UIViewController { UIBarButtonItem *item; } @property (nonatomic, retain) UIBarButtonItem *item; @end @implementation MyViewController @synthesize item; -(void)viewDidLoad { // assuming item isn't in your NIB item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlus target:self action:@selector(doit)]; self.navigationItem.rightBarButtonItem = item; } -(void)doit { UIPopoverController *popover = [[[UIPopoverController alloc] initWithContentViewController:yourViewController] autorelease]; [popover presentPopoverFromBarButtonItem:self.item permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; // or in the line above, replace self.item with self.navigationItem.rightBarButtonItem } @end 
0
source

Say you added UIButton aButton to UIBarButtonItem info_Button as follows:

 //Add a button on top of the UIBarButtonItem info_button UIButton *aButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; [aButton addTarget:self action:@selector(showInfo:) forControlEvents:UIControlEventTouchUpInside]; info_Button.customView = aButton; 

Now, in showInfo, presentPopoverFromBarButtonItem: info_Button (instead of currentPopoverFromBarButtonItem: sender), this will pass UIBarButtonItem info_button to do pop over works:

 - (IBAction)showInfo:(id)sender { [self.flipsidePopoverController presentPopoverFromBarButtonItem:info_Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } 
0
source
 // get the UIBarButtonItem from the UIButton that is passed in sender UIToolbar *toolbar = (id)[sender superview]; UIBarButtonItem *ourButtonItem = [toolbar items][2];//pick the right index [parkingPopOver_ presentPopoverFromBarButtonItem:ourButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 
0
source

Source: https://habr.com/ru/post/909673/


All Articles