24

How can I change the title of a UIBarButtonItem? I have the following code which is called when an edit button is pressed on my UINavigationBar.

-(void)editButtonSelected:(id)sender {
    NSLog(@"edit button selected!");
    if(editing) {
        NSLog(@"notediting");
        [super setEditing:NO animated:NO];
        [tableView setEditing:NO animated:NO];
        [tableView reloadData];
        [rightButtonItem setTitle:@"Edit"];
        [rightButtonItem setStyle:UIBarButtonItemStylePlain];
        editing = false;
    }
    else {
        NSLog(@"editing");
        [super setEditing:YES animated:YES];
        [tableView setEditing:YES animated:YES];
        [tableView reloadData];
        [rightButtonItem setTitle:@"Done"];
        [rightButtonItem setStyle:UIBarButtonItemStyleDone];
        editing = true;
    }
}

The edit button is changing color (so the line which sets the style is working), however the line which sets the title of the button is not working.

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
CodeGuy
  • 28,427
  • 76
  • 200
  • 317

8 Answers8

35

I've done the following to dynamically change the title of a UIBarButtonItem. In this situation I am not using a UIViewTableController and cannot use the standard editButton. I have a view with a tableView as well as other subviews and wanted to emulate the behavior of the limited UIViewTableController.

- (void)InitializeNavigationItem
{
    NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:2];
    UIBarButtonItem* barButton;

    barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                                                              target:self 
                                                              action:@selector(addNewItem:)];
    barButton.style = UIBarButtonItemStyleBordered;
    [array addObject:barButton];

    // --------------------------------------------------------------------------------------

    barButton = [[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStyleBordered
                                                              target:self 
                                                              action:@selector(editMode:)];
    barButton.style = UIBarButtonItemStyleBordered;
    barButton.possibleTitles = [NSSet setWithObjects:@"Edit", @"Done", nil];
    [array addObject:barButton];

    self.navigationItem.rightBarButtonItems = array;
}

- (IBAction)editMode:(UIBarButtonItem *)sender
{
    if (self.orderTable.editing)
    {
        sender.title = @"Edit";
        [self.orderTable setEditing:NO animated:YES];
    }
    else
    {
        sender.title = @"Done";
        [self.orderTable setEditing:YES animated:YES];
    }
}

Note that I didn't use the the UIBarButtonSystemItemEdit barButton, you cannot manually change the name of that button, which makes sense.

You also might want to take advantage of the possibleTitles property so that the button doesn't resize when you change the title.

If you are using a Storyboard/XIB to create/set these buttons, ensure that the Bar Button Item Identifier is set to Custom for the button which you'd want to control the title for.

Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
Seamus
  • 3,191
  • 3
  • 22
  • 20
  • I think the call to barButton.possibleTitles is redundant. I found this worked just by setting the type of the caller on the editMode method and using sender.title = @"something" – Simon Curd Sep 22 '13 at 08:02
  • 2
    Thanks @Seamus! The trick for me was to NOT use the "Edit" button that would normally work in a UITableViewController. I believe that because it was the native "Edit" button it wasn't letting me change the title. I set mine to "Custom". – kbpontius May 28 '15 at 20:37
  • +1 to the `possibleTitles`. Weird that you have to declare the possibilities up front, but this seemed to resolve this for me. – mylogon May 06 '17 at 22:51
  • `If you are using a Storyboard/XIB to create/set these buttons, ensure that the Bar Button Item Identifier is set to Custom for the button which you'd want to control the title for.` That's what I was looking for. Thanks! – Phontaine Judd Oct 28 '19 at 05:00
24

I had this problem and resolved it by setting the UIBarButtonItem style to the custom type when it's initialised. Then the titles would set when changing their title values.

You may also want to set the possibleTitle value in the viewDidLoad method to ensure the button is sized correctly for all the possible titles it can have.

Mark Bridges
  • 8,228
  • 4
  • 50
  • 65
  • Super simple solution -- works fine. I'm using storyboards, so even with a multipurpose edit button, you can intercept user touches with - (BOOL) shouldPerformSegueWithIdentifier: and doing custom actions. Thanks a million for this simple (and what should have been obvious) solution! – Mike Critchley Jan 30 '16 at 08:35
  • yea, Custom type will let you access the title – Edward Ashak Mar 23 '16 at 23:03
8

In my case what prevented the title being displayed was that in the xib I'd selected the Bar button item 'identifier' property as 'Cancel'.

enter image description here

I tried setting the title property even before assigning the button to the navigation bar, but the title was not being updated.

I made it like this:

enter image description here And it started working just as I wanted.

Joe M
  • 669
  • 6
  • 9
8

If you look at the documentation of the title property, it is explicitly mentioned that you should set it before assigning it to the navigation bar. Instead of doing what you're doing right now, you can use two bar button items – one for done and one for edit, and set them alternatively.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
Deepak Danduprolu
  • 44,595
  • 12
  • 101
  • 105
  • 1
    Exactly! e.g.: It is enough to code: UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(someMethod)]; to create a Done button. – Oscar Salguero Mar 02 '12 at 00:33
  • 7
    Yes, it does say you should set the title before adding, but what then is the sense of the possibleTitles property? – Gordon Dove Oct 26 '12 at 15:59
  • I added the bar button programmatically and set the `possibleTitles` property. I had no problem changing the `title` property on the fly -- as Gordon says -- what the point of the `possibleTitles` property if the title can't be changed? – wcochran Jun 22 '14 at 22:00
  • `possibleTitles` is to provide alternatives for when there is more or less space on the navigation bar (e.g. landscape vs portrait, iPhone 4 vs iPhone 6 Plus vs iPad). – jrc Oct 14 '15 at 23:40
2

Actually if all you want if switching between "Edit" and "Done", just use self.navigationItem.rightBarButtonItem = self.editButtonItem;

It will handle this transition for you

gyan
  • 219
  • 1
  • 7
  • 2
    This would switch a button and not change the title as the question asks. – Steve Buzonas Jan 19 '15 at 21:55
  • I don't know how apple implements this editButtonItem, but it does behave like one single button switching between "Edit" and "Done". If you want to change the title to anything else, this will not work. But from the code OP posted, this is exactly what he needs. – gyan Jan 19 '15 at 22:09
  • If he's using `UIBarButtonSystemItemEdit` then yes apple utilizes a lot of immutable objects, and it makes sense to not be able to change the title from "Edit" to "Done" on a class with the word edit in it. – Steve Buzonas Jan 19 '15 at 22:21
1

Just switch out the buttons each time the user presses them.

- (void)setNavigationButtonAsEdit
{
    UIBarButtonItem* editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit", @"")
                                                                   style:UIBarButtonItemStylePlain
                                                                  target:self
                                                                  action:@selector(editButtonPressed:)];

    self.navigationItem.rightBarButtonItems = [NSArray arrayWithObject:editButton];
}

- (void)setNavigationButtonAsDone
{
    UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", @"")
                                                                   style:UIBarButtonItemStylePlain
                                                                  target:self
                                                                  action:@selector(editButtonPressed:)];
    self.navigationItem.rightBarButtonItems = [NSArray arrayWithObject:doneButton];
}

And then create an IBAction to handle the button press:

- (IBAction)editButtonPressed:(id)sender
{
    NSString* buttonText = [sender title];
    if ([buttonText isEqualToString:NSLocalizedString(@"Edit",@"")])
    {
        [self setNavigationButtonAsDone];
    }
    else
    {
        [self setNavigationButtonAsEdit];
    }
}
Scott Allen
  • 1,199
  • 1
  • 12
  • 14
1

Swift 3.0, 3.2, or 4.0

If your custom ViewController containing a tableView object follows the UITableViewController Delegate and Datasource protocols, you can append a system editBarButtonItem to your navigationItem.leftBarButtonItem(s) or navigationItem.rightBarButtonItem(s) with the following code:

func setupTableView() {
    tableView.delegate = self
    tableView.dataSource = self
    navigationItem.rightBarButtonItem = editButtonItem
    editButtonItem.action = #selector(CustomViewController.editTableView(_:))
    
}

@objc func editTableView(_ sender: UIBarButtonItem) {
    tableView.isEditing = !tableView.isEditing
    if tableView.isEditing {
        sender.title = "Done"
    } else {
        sender.title = "Edit"
    }
}
Community
  • 1
  • 1
umarqattan
  • 499
  • 1
  • 6
  • 13
-1

Try:

UIButton *rightButton;
rightButton = (UIButton*)self.navigationItem.rightBarButtonItem.customView;
[rightButton setTitle:@"Done" forState:UIControlStateNormal];

Because rightBarButtonItem.customView == “the button your added”.

Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
dadoftutu
  • 49
  • 4