How to set target and action for UIBarButtonItem at runtime
Asked Answered
S

12

70

Tried this but only works for UIButton:

[btn setTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
Succinic answered 25/2, 2010 at 11:36 Comment(2)
That does not appear to be valid even for UIButton.Bakki
For UIButton, the right method is -addTarget:action:forControlEvents:Lanellelanette
D
113

Just set the UIBarButtonItem's target and action properties directly.

Donela answered 25/2, 2010 at 11:41 Comment(10)
N.B. This only works if the UIBarButtonItem doesn't use a custom view, like a UIButtonQuinones
For custom views, use: [button addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];Sato
Can you please give an example of what those should be set to? The target says it takes an AnyObject? Should that be set to a UIGestureRecognizer?Corcovado
assuming btn is a UIBarButtonItem, [btn setTarget:self]; [btn setAction:@selector(btnClicked:)] or DOT notation btn.target = self; btn.action = @selector(btnClicked:); Both should work as @Ole-Begemann is describing.Gildea
@Gildea hey, does it still work (6 years later)? how can I set a target and action to a UITabBarItem today?Honorable
@wp42 Should still work. This was just used last year on my end.Gildea
Per the documentation this doesn't work on an instance that has been initialized with a custom view. "The bar button item created by this method does not call the action method of its target in response to user interactions. Instead, the bar button item expects the specified custom view to handle any user interactions and provide an appropriate response." See apple.co/2egXdmR for referenceTrousseau
This only works if the UIBarButtonItem doesn't use a custom viewNoway
Did you figure out what worked if you used a custom view?Demetria
For a custom view where you add a UIButton, button, to a UIBarButtonItem, barButtonItem: button.addTarget(self, action: #selector(yourFunction), for: .touchUpInside). In other words, add it to the button that you're adding to the barbuttonitem.Formenti
G
28

UIBarButtonItem doesnt have the same addTarget method so you have to set them directly as follows

btn.target = self;
btn.action = @selector(barButtonCustomPressed:);

...

// can specify UIBarButtonItem instead of id for this case
-(IBAction)barButtonCustomPressed:(UIBarButtonItem*)btn 
{
    NSLog(@"button tapped %@", btn.title);
}
Galvanize answered 11/9, 2014 at 20:36 Comment(2)
Thank you!! this is exactly what i needed to implement my custom UIBarButtonItem classCounterattraction
great answer, especially if you want to create the buttons at design time!Berwickupontweed
I
18

Set target and action of your UIBarButtonItem

Swift 5 & 4

button.target = self
button.action = #selector(action)

@objc func action (sender:UIButton) {
    print("action")
}
Irvinirvine answered 10/10, 2017 at 12:40 Comment(1)
This only works if the UIBarButtonItem doesn't use a custom view.Noway
D
15

I ran into a similar problem... I assume you mean that if your UIButton is not part of your UITabBar to call btnClicked then it works appropriately. If this is the problem you are proposing then, check your btnClicked method and change it from:

-btnClicked:(id)sender

to

-(void) btnClicked:(id)sender

that, and declare btnClicked in the header file...

For what it's worth, this is how I setup a button in tabbarbuttonitem:

UIBarButtonItem *exampleButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"button.png"] style:UIBarButtonItemStylePlain target:self action:@selector(btnClicked:)];
Divisible answered 28/2, 2010 at 4:56 Comment(1)
additionally, you can take out the ":" making ...:@selector(btnClicked:)]; into ...:@selector(btnClicked)];Divisible
P
9

If you need this enough times in your code, it's nice to go ahead and extend UIBarButtonItem which I've done below in Swift. :)

import UIKit

extension UIBarButtonItem {
    func addTargetForAction(target: AnyObject, action: Selector) {
        self.target = target
        self.action = action
    }
}

As an example, with self as a UIViewController, you'd simply call:

self.myBarButtonItem.addTargetForAction(self, action: #selector(buttonPressed(_:))
Perrault answered 11/8, 2015 at 14:56 Comment(1)
This is a bad name, it suggests that previous target/actions are preserved as is the case with UIButtonLuana
O
7
UIBarButtonItem *barListBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemAdd target:self action:@selector(getTruckStopListAction)];   
self.navigationItem.rightBarButtonItem = barListBtn;
[barListBtn release];
Overestimate answered 14/3, 2012 at 7:1 Comment(0)
F
2

For a custom UIBarButtonItem this works.

let button = UIButton(type: .custom)
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(yourFunction), for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)

You set the target and action to the button that you are adding to your UIBarButtonItem.

Formenti answered 29/7, 2022 at 19:59 Comment(0)
I
1

@wp42 It does work today.

A nifty way of doing this in objective-C is adding a category to UIBarButtonItem class:

.h file

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (addons)

-(void)addTarget:(id)target andAction:(SEL)action;

@end

.m file

#import "UIBarButtonItem+addons.h"

@implementation UIBarButtonItem (addons)

-(void)addTarget:(id)target andAction:(SEL)action{
   [self setTarget:target];
   [self setAction:action];
}

@end

In practice:

[myBtn addTarget:self andAction:@selector(myFunction:)];
Insured answered 8/9, 2016 at 19:58 Comment(0)
H
1

For custom views: use an UITapGestureRecognizer and set up isUserInteractionEnabled to true.

profileImageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(handleProfileImageTap))
profileImageView.addGestureRecognizer(tap)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: profileImageView)
Holophytic answered 19/11, 2020 at 8:38 Comment(0)
D
0

If you are programmatically adding the UIBarButtonItem, the best way to set the target and action is to initialize the button with one of the following methods:

UIBarButtonItem *customButton = [[UIBarButtonItem alloc] initWithImage:<#(UIImage)#> style:<#(UIBarButtonItemStyle)#> target:<#(id)#> action:<#(SEL)#>

UIBarButtonItem *customButton = [UIBarButtonItem alloc] initWithTitle:<#(NSString *)#> style:<#(UIBarButtonItemStyle)#> target:<#(id)#> action:<#(SEL)#>

UIBarButtonItem *customButton = [UIBarButtonItem alloc] initWithImage:<#(UIImage *)#> landscapeImagePhone:<#(UIImage *)#> style:<#(UIBarButtonItemStyle)#> target:<#(id)#> action:<#(SEL)#>
Dejadeject answered 6/1, 2015 at 20:47 Comment(0)
G
0

Swift 5:

Extract to extensions:

extension UIBarButtonItem {

    static func nextBtn(target: AnyObject, action: Selector) -> UIBarButtonItem {
        let title = "Next"
        return button(title: title, target: target, action: action)
    }

    private static func button(title: String, target: AnyObject, action: Selector) -> UIBarButtonItem {
        return UIBarButtonItem(title: title, style: .done, target: target, action: action)
    }

}

Call in code:

navigationItem.rightBarButtonItem = .nextBtn(target: self, action: #selector(rightBarButtonAction))

Action:

@objc func rightBarButtonAction() {
    Swift.print("Button tapped!")
}

Pretty easy to add new buttons to this factory.

Guardhouse answered 5/11, 2019 at 8:52 Comment(0)
B
-5

You may want to try out the addTarget method.

Bookbinding answered 9/11, 2010 at 10:21 Comment(2)
There is no addTarget method for UIBarButtonItem.Defile
That methohd does not exist, check the docs please: developer.apple.com/library/IOs/documentation/UIKit/Reference/… What you are thinking of is a UIButtonRemediosremedy

© 2022 - 2024 — McMap. All rights reserved.