I\'ve got a custom view inside of a UIBarButtonItem, set by calling -initWithCustomView.
My bar button item renders fine, but when I tap it, it doe
I do not think the target and action of the UIBarButtonItem apply to custom views. Try using a UIButton instead of UIImageView and applying the target and action to the button.
Sample code in Swift:
let button = UIButton(type: .Custom)
if let image = UIImage(named:"icon-menu.png") {
button.setImage(image, forState: .Normal)
}
button.frame = CGRectMake(0.0, 0.0, 30.0, 30.0)
button.addTarget(self, action: #selector(MyClass.myMethod), forControlEvents: .TouchUpInside)
let barButton = UIBarButtonItem(customView: button)
navigationItem.leftBarButtonItem = barButton
If you do not want to settle with an UIImage and have a custom view in your barbuttonitem, set a tap gesture recognizer to your barbuttonitem's customview property
let tap = UITapGestureRecognizer(target: self, action: #selector(goProButtonPressed))
deviceStatusBarButtonItem.customView?.addGestureRecognizer(tap)
Jacob, everything looks good, however you may not have provided the correct selector.
Can you verify that your action is actually declared
- (void) deselectAll;
and not
- (void) deselectAll:(id)sender;
If it's the latter, you will need to set the action to @selector(deselectAll:). (note the semi-colon to match the method declaration)
Also, void might be IBAction, but that's not relevant to this problem you're having.
Is your custom view eating touch events or passing them on to parent view?
To make this easy to work with, I created a category on UIBarButtonItem which looks like this:
@implementation UIBarButtonItem (CustomButtonView)
- (void)setButtonImage:(UIImage *)image
{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:image forState:UIControlStateNormal];
[button sizeToFit];
[button addTarget:self.target action:self.action forControlEvents:UIControlEventTouchUpInside];
self.customView = button;
}
- (UIImage *)buttonImage
{
return [(UIButton *)self.customView imageForState:UIControlStateNormal];
}
@end
In your client code, simply use:
myBarButtonItem.buttonImage = [UIImage imagedNamed:@"image_name"];
Done this way you can still hook up your targets and actions in IB (pushing as much UI config into IB as you can is a Good Thing).
I had a similar problem. And I initially followed the path suggested by @drawnonward, but then ran into trouble when I tried to have my action present a popover controller on an iPad: Using an embedded UIButton as a custom view means the UIButton is the sender of the event, and the popover controller’s presentPopoverFromBarButtonItem: method crashes when it tries to send it messages which are only appropriate to actual UIBarButtonItems.
The solution I eventually found was to steal the image I wanted to use (the “info” icon) from a throwaway UIButton, and construct my UIBarButtonItem as follows:
// Make the info button use the standard icon and hook it up to work
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
UIBarButtonItem *barButton = [[[UIBarButtonItem alloc]
initWithImage:infoButton.currentImage
style:UIBarButtonItemStyleBordered
target:self
action:@selector(showInfo:)] autorelease];
Using this initializer yields a bar button whose target and selector actually work. It is also easier than wrapping the image in a custom view, but that is just icing.