Jagie
Jagie

Reputation: 2220

How to get the embedded button of UIBarButtonItem

In an iPhone app,we can make a UIBarButtonItem by using the following code:

UIBarButtonItem *bbix=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];

the generated UIBarButtonItem has a system-provided "action" icon.My question is :how to get this UIBarButtonItem's inner UIButton and add this UIButton to another UIView? who can show me some code?

Upvotes: 8

Views: 12784

Answers (7)

Augustine
Augustine

Reputation: 1714

Accessing the "customView" property of the bar button item is one possible solution:

UIBarButtonItem *item = (UIBarButtonItem *)[self.navigationItem.rightBarButtonItems objectAtIndex:0];
                     OR
UIBarButtonItem *item = (UIBarButtonItem *)[self.navigationItem.rightBarButtonItem];

UIButton *myBtn;

if([item.customView isKindOfClass:[UIButton class]]) 
{ 
    myBtn = (UIButton*)item.customView;
}

if(myBtn)
{
    // do something
}

Try this out. It really works for me :)

Upvotes: 6

sven7
sven7

Reputation: 758

Here is a solution that precisely replicates the UIBarButtonItem image that is otherwise acquired by using the UIBarButtonSystemItemAction system type. As an example, the newly created UIButton is inserted into an MKAnnotationView:

Create a category file that contains this method:

@implementation UIImage (Custom)

+ (UIImage *)actionButtonImage
{
    CGRect rect = CGRectMake(0, 0, 20, 27);

    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);

    [[UIColor colorWithRed:3/255.0 green:122/255.0 blue:1 alpha:1] set];

    UIBezierPath *path = [UIBezierPath bezierPath];

    // Box
    [path moveToPoint:CGPointMake(7, 8)];
    [path addLineToPoint:CGPointMake(1, 8)];
    [path addLineToPoint:CGPointMake(1, 26)];
    [path addLineToPoint:CGPointMake(19, 26)];
    [path addLineToPoint:CGPointMake(19, 8)];
    [path addLineToPoint:CGPointMake(13, 8)];

    // Arrow shaft
    [path moveToPoint:CGPointMake(10, 17)];
    [path addLineToPoint:CGPointMake(10, 1)];

    // Arrow head
    [path moveToPoint:CGPointMake(6, 4.5)];
    [path addLineToPoint:CGPointMake(10, 0.5)];
    [path addLineToPoint:CGPointMake(14, 4.5)];

    [path stroke];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

@end

In the MKMapView delegate, add this implementation (adapt as desired):

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    MKPinAnnotationView *view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"Item"];
    view.canShowCallout = YES;

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    UIImage *actionImage = [UIImage actionButtonImage];
    [button setImage:actionImage forState:UIControlStateNormal];
    button.frame = CGRectMake(0, 0, actionImage.size.width, actionImage.size.height);
    view.leftCalloutAccessoryView = button;

    return view;
}

Upvotes: 0

Bradley Thomas
Bradley Thomas

Reputation: 4107

If you have created your bar button item via initWithCustomView, simply access the custom view property and cast to UIButton.

http://cocoatouch.blog138.fc2.com/blog-entry-214.html

Upvotes: 0

Chris
Chris

Reputation: 1539

Just to extend Brians answer if your UIBarButton is made with custom view...

if ([myBarButton.customView.subviews.lastObject isKindOfClass:[UIButton class]])
{
    UIButton * btn = ((UIButton *)(myBarButton.customView.subviews.lastObject));
}

Just add a little bit of error checking, you never know when apple or another developer will one day change the layout hierarchy. Since this approach is really error prone long term.

Upvotes: 0

Ahmad Houri
Ahmad Houri

Reputation: 1207

You can't access the embedded button inside UIBarButtonItem through the UIBarButtonItem

what you can do it to link the inner button using the interface builder with a new outlet and like this you can access to the button directly you can find the button inside the objects view when you open the nib file then you can link it with a new outlet

Upvotes: 1

D.D.
D.D.

Reputation: 333

I don't think you can get the embedded button in any case. However, if you create a button using a custom view, for example, using a button, we can get that button later using this code:

((UIButton *)(theBarButtonItem.customView.subviews.lastObject));

The hierarchy of the custom view should like this:

|--UIView
  |--UIButton
  |--UIImageView

Hopes that helps.

Upvotes: 3

Shaggy Frog
Shaggy Frog

Reputation: 27601

You can't. UIBarButtonItem inherits from UIBarItem which inherits from NSObject. None of those classes has a method to get a UIButton, because UIBarButtonItem isn't a UIButton.

Contrariwise, you can create a UIBarButtonItem from a UIButton -- see an answer I gave to a different question for more info (which works by adding it as a "custom view").

Upvotes: 13

Related Questions