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.