How to change a UIBarButtonItem in a UINavigationBar - iphone

I'm trying to set up a list of items that can be edited. I have a main view, with a UINavigationBar at the top and a UITableView directly under it. I'd like to have my "edit" button change to a "done" button on click, but I can't figure out how to do it.
If I could do it in the code (not it interface builder), I could just replace it, but I can't even do that. I've seen some code using [self.navigationItem], but in my case self is a UIView.
It also feels a bit odd to be using a UINavigationBar when I don't want navigation (this is one page only), but I want a toolbar with a title and and a button, so I don't think really have a choice.

I create one button that can change from Edit to Done. It's a tip from More iPhone Development book.
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *editButton = self.editButtonItem;
[editButton setTarget:self];
[editButton setAction:#selector(toggleEdit)];
self.navigationItem.leftBarButtonItem = editButton;
}
And the method toggleEdit
- (IBAction)toggleEdit {
BOOL editing = !self.tableView.editing;
self.navigationItem.rightBarButtonItem.enabled = !editing;
if (editing) {
self.navigationItem.leftBarButtonItem.title = NSLocalizedString(#"Done", #"Done");
//Added in the edition for this button has the same color of the UIBarButtonSystemItemDone
self.navigationItem.leftBarButtonItem.style = UIBarButtonItemStyleDone;
} else {
self.navigationItem.leftBarButtonItem.title = NSLocalizedString(#"Edit", #"Edit");
//Added in the edition for this button has the same color of the UIBarButtonSystemItemDone
self.navigationItem.leftBarButtonItem.style = UIBarButtonItemStylePlain;
}
[self.tableView setEditing:editing animated:YES];
}
Then you don't need replace any of them.

When you use self.editButtonItem, you don't need to change the style and text of the button, it is done automatically. Try removing that code, it will still work :)

set up nav button in IB with the following linked in IB and create an outlet called editOutlet and and an action called editToggle in your header file and your method is as easy as this:
-(IBAction) editToggle:(id) sender {
if (self.tableViewOutlet.isEditing == NO) {
self.editOutlet.title = NSLocalizedString(#"Done", #"Done");
self.editOutlet.style = UIBarButtonItemStyleDone;
[self.tableViewOutlet setEditing:YES animated:YES];
}else {
self.editOutlet.title = NSLocalizedString(#"Edit", #"Edit");
self.editOutlet.style = UIBarButtonItemStylePlain;
[self.tableViewOutlet setEditing:NO animated:YES];
}
}

Got it! Looks like you can get to the UINavigationItem by using the topItem property. Just had to read through the docs, like always!

you can try it
[self setValue:viewController.navigationItem forKey:#"_navigationItem"];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];

Related

Enable Edit Mode in ViewController

I'm new on iOS development, i m trying to show a user profile inside a view, and in the same time i want to give a user a possibility to edit his profile by tapping an "Edit" button on the UINavigationBar like shown on Apple web site : Enabling Edit Mode in a View Controller
I tried to find a tutorial explaining all this, but i didn't fin anything. can somebody help me plz, by giving me a link for a tutorial, or a sample code ?
PS : I m using storyboard.
Thanks a lot !
Here and here are a couple of examples for a UITableview
The concept is the same. You add a UIBarButtonItem and change the current mode of the tableView and the status(text) of the buttonItem to show the editing dashes and other content if you choose.
Here is a simple edit mode button press to send the tableView into edit mode to allow for easy deleting. You can also
- (IBAction)editPressed:(id)sender
{
// If the tableView is editing, change the barButton title to Edit and change the style
if (_theTableView.isEditing) {
UIBarButtonItem *newButton = [[UIBarButtonItem alloc]initWithTitle:#"Edit" style:UIBarButtonSystemItemDone target:self action:#selector(editPressed:)];
self.navigationItem.rightBarButtonItem = newButton;
_buttonEdit = newButton;
[_theTableView setEditing:NO animated:YES];
}
// Else change it to Done style
else {
UIBarButtonItem *newButton = [[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonSystemItemEdit target:self action:#selector(editPressed:)];
self.navigationItem.rightBarButtonItem = newButton;
_buttonEdit = newButton;
[_theTableView setEditing:YES animated:YES];
}
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
// You could do other things in here based on whether editing is true or not
}
You can set default edit button to you navigationItem barbutton inside viewDidLoad as shown below.
-(void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
As give in the apple document
editButtonItem - Returns a bar button item that toggles its title and associated state between Edit and Done. The default button action invokes the setEditing:animated: method.
Override setEditing:animated: in your view controller as shown below.
-(void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
}
You can make use of bool variable editing to achieve your requirements.

iPhone custom navigation bar with custom UIBarButtonItems

I'm trying to create a custom navigation bar with title and two custom baritems.
What I've done so far:
1. subclass a UINavigationBar
2. override -(void) drawRect:(CGRect)rect method, to draw image as a background
Now I get stuck when making right bar button item.
In my CustomBar class I've overriden pushNavigationItem method as follows:
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated {
[super pushNavigationItem:item animated:NO];
item.rightBarButtonItem.customView.frame = CGRectMake(250, 5, 60,30);
}
and in my view controller I've done something like:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationController.navigationItem.rightBarButtonItem = barButton;
[self.navigationController.navigationBar pushNavigationItem:self.navigationItem animated:NO]
but I always get SIGABRT when calling
[super pushNavigationItem:item animated:NO];
If I leave that line out, everything runs fine, but there is no button in the navigation bar.
What is the proper way to add custom bar button item to custom navigation bar?
EDIT:
For clarification, I've added an image.
This is what I need.
I'm trying to create the logout button on the right
Have you tried removingnavigationController while setting the item ? I used to do that for setting the title, never used to get the title.
Try [[self navigationItem] setRightBarButtonItem:yourButton];
In your case :
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationItem.rightBarButtonItem = barButton;`

iPhone Storyboard Editing a table view

I've been trying to learn the new Storyboard feature in Xcode and I've run into a problem with trying to set a UITableView to edit mode.
So far my storyboard looks like this:
NavigationController -> UIViewController (subclass with tableview property)
I added a Navigation Item and a Bar Button item to the view controller scene, so I do see an edit button. It didn't do anything automagically, so I tried linking it's selector to the setEditing method of the tableview delegate. This did put it into editing mode. However, the edit button did not change to a "Done" button and so there is no way to get out of editing mode.
Do I have to create another Navigation item for the Done button? How do I connect it so that it appears at the right time and works correctly?
I think that also with Storyboard, the only way (for sure, the easiest one) to implement a working edit/done button, is to use the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
...
//set the edit button
self.navigationItem.leftBarButtonItem = self.editButtonItem;
...
This is the solution that Apple itself implements if you select a "Master-Detail Application" template for your project.
Probably Storyboard is still not perfect, and hopefully it will be improved from Apple in next releases...
I just started using Storyboards, so I also wanted to use the Storyboard to add my Edit button. It is annoying to have taken the time to learn how to use a new tool but find you need a roll of duct tape to patch up the holes.
You can get it to work, but need to add a Custom button. In the Attributes inspector make sure the Identifier is Custom and the title is Edit.
Then add something like this in your .m
- (IBAction)setEditMode:(UIBarButtonItem *)sender {
if (self.editing) {
sender.title = #"Edit";
[super setEditing:NO animated:YES];
} else {
sender.title = #"Done";
[super setEditing:YES animated:YES];
}
}
Have your Custom Edit button call the setEditMode method.
Can only hope they will fix the implementation of the Edit button in the Storyboard editor in the future.
To summarize:
The Button, returned by UIViewController.editButtonItem is a special toggling button with special behavior that calls - (void)setEditing:(BOOL)editing animated:(BOOL)animated if pressed.
The Button, returned by UINavigationController.editButtonItem is a simple Button, just labeled with "Edit".
The Storyboard allows to select the latter one.
If you are using the navigation controller to push to the view controller, simply set self.navigationItem.rightBarButtonItem = self.editButtonItem;, which will put the default Edit button in the right. If the navigation bar is not visible, call self.navigationController.navigationBarHidden = NO;. Those would be called in the viewDidLoad method, or something similar. Then in order to get the tableView to respond to the edit call, use the following method:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[tableView setEditing:editing animated:animated];
}
That should do what you want it to do. If you have any issues, just say so and we can narrow down the details
To add to #Graham answer, you might also want to change the style so you can have the "Done" button style (the blue color). Something like this:
- (IBAction)setEditMode:(UIBarButtonItem *)sender {
if (self.editing) {
sender.title = #"Edit";
sender.style = UIBarButtonItemStylePlain;
[super setEditing:NO animated:YES];
} else {
sender.title = #"Done";
sender.style = UIBarButtonItemStyleDone;
[super setEditing:YES animated:YES];
}
}
one can use the dumb, not working Edit button from the Storyboard editor and then programmatically replace it with the UIViewController.editButtonItem.
in viewDidLoad:
NSMutableArray *toolbarItems = [NSMutableArray arrayWithArray:self.toolbarItems];
[toolbarItems replaceObjectAtIndex:0 withObject:self.editButtonItem];
[self setToolbarItems:toolbarItems];
this code assumes one has added the dumb Edit button as the leftmost item on the toolbar in the Storyboard.
In case that you have UIViewController and inside this you added a UITableVIew.
If you want to add an edit UIBarButton in order to interact with UITableView, try:
Add this line...
- (void)viewDidLoad
{
[super viewDidLoad];
...
self.navigationItem.leftBarButtonItem = self.editButtonItem;
...
}
and this method
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.myListTableView setEditing:editing animated:animated];
if(self.myListTableView.editing) {
NSLog(#"editMode on");
} else {
NSLog(#"editMode off");
}
}
where
#property (weak, nonatomic) IBOutlet UITableView *myListTableView;

How to change UIBarButtonItem's type in UINaviagationBar at runtime?

I am working on an iPhone's view which composed 3 elements, UITextView, UIToolBar with an UIBarButtonItem.
The goal is, I want UIBarButtonItem change its style from 'edit' (UIBarButtonSystemItemEdit) to 'Done' (UIBarButtonSystemItemDone) and update new selector to new method.
First of all, I have tried following code but it doesn't work:
Could you help me on this idea?
There is a builtin bar button with this behaviour, you get it via the editButtonItem property of a UIViewContoller. Tabbing that button will change the view controller it came from into editing mode, and toggle the button into a done button.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
If you have added the button through IB then make sure to set the identifier to Custom
Also allocate a button in the .h with appropriate IBOutlet and Property
Synthesize the button in .m
Then in your code do the following:
// Set to done
editButton.style = UIBarButtonItemStyleDone;
editButton.title = #"Done";
// Set back to edit
editButton.style = UIBarButtonItemStyleBordered;
editButton.title = #"Edit";
to change the button the Done button use this
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
to change the button to Edit button use this
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleBordered];
I ended up doing something like this. Unfortunately, setting the title directly did not work, for some reason it was nil and would not let me set it to a different value. The self.editButton comes from an IBOutlet with the target and actions set. This code uses ARC. I hope this helps someone.
NSString *title = app.settings.editing
? NSLocalizedString(#"Done", #"")
: NSLocalizedString(#"Edit", #"");
UIBarButtonItemStyle style = app.settings.editing
? UIBarButtonItemStyleDone
: UIBarButtonItemStyleBordered;
UIBarButtonItem *editButton
= [[UIBarButtonItem alloc] initWithTitle:title
style:style
target:self.editButton.target
action:self.editButton.action];
self.navigationItem.rightBarButtonItem = editButton;

Is there a better way to hide the backBarButtonItem than this?

I have a way of hiding the back button used by the navigation controller. It's set by the previous controller, not the one managing the current view, and that makes it tricky to get to. I needed to do this in editing mode so that I could prevent the user from navigating away from the screen.
if(self.editing) {
// Get rid of the back button
UIView *emptyView = [[UIView alloc] init];;
UIBarButtonItem *emptyButton = [[[UIBarButtonItem alloc] initWithCustomView:emptyView] autorelease];
[self.navigationItem setLeftBarButtonItem:emptyButton animated:YES];
} else {
// Restore the back button
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
}
Is there a better way to do this?
use this to hide back button
[self.navigationItem setHidesBackButton:YES]
use this to show back button
[self.navigationItem setHidesBackButton:NO]
Here's the method I use in my view controller to show and hide the back button when editing is enabled and disabled:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
if (editing) {
// Disable the back button
[self.navigationItem setHidesBackButton:YES animated:YES];
}
else {
// Enable the back button
[self.navigationItem setHidesBackButton:NO animated:YES];
}
[super setEditing:editing animated:animated];
}
Make an outlet with strong (not weak as default) of the bar button from the storyboard to your view controller.
The purpose is not to loose the reference when you set the left/right bar button to nil.
Swift5:
self.navigationItem.setHidesBackButton(true, animated: false)