UIBarButton won't show in my UINavigationController - ios

I want to make a simple view with a navigation bar and a table view. So I created a subclass of UINavigationController and I added a UITableView in it. My is is also the UITableViewDataSource and UITableViewDelegate. Now I want to add UIBarButton in the navigation bar but it doesn't work :
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:[[Translator instance] getTranslation:#"Back"]
style:UIBarButtonItemStylePlain
target:self.parentViewController
action:#selector(dismissFiltersModal:)];
self.navigationItem.backBarButtonItem = anotherButton;
There's no error the view is displayed but not the button. How can I do to display it?

jafar,
as Apple doc suggested you should avoid to subclass UINavigationController.
This class is not intended for subclassing.
Said this, you could follow these simply steps (some advice for you):
Create your controller (say MyController) that extends UIViewController and add the table here. Set your controller as the delegate and data source for that table. If you have created by xib you need an outlet for your table view.
[P.S. you could also subclass a UITableViewController, it has a table view its own]
In viewDidLoad of MyController customize the navigation bar.
For example
UIBarButtonItem* myButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(someSelector)];
self.navigationItem.leftBarButtonItem = myButton;
You could also customize the title.
For example
self.title = #"Your custom title";
Somewhere in your code create a UINavigationController and add as a root view controller an instance of MyController.
For example:
MyController* myCtr = // alloc-init here
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:myCtr];

The backBarButtonItem should be set on the previous view controller, not the current one to be displayed. For example, if your you are on view A, navigate to B from it, inside B A's backBarButtonItem will be displayed, not B's.
If you just want to display an item on the left hand side of the navigation bar, you can use leftBarButtonItem instead, which will display a normal bar button on that controller. It will be rectangular, not an arrow like normal back buttons though.

How about you try this :
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:#selector(dismissFiltersModal:) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
// create button item --
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
// add to toolbar
self.navigationItem.leftBarButtonItem = backItem;

Related

How do I create a persistent button on the bottom of a navigation controller?

I have a master / detail based iPhone app. Without using a tabbed navigation style application, how do I create a persistent button at the bottom of the navigation controller ( I want it on every view ). Please wireframe ( its the plus button ). I've tried adding a button bar item to the toolbar at the bottom, but for some reason it won't show up. I'm using xcode 8 and ios 10.
for reference I created a custom navigation controller class and inserted the following code
#import "MainNavigationController.h"
#interface MainNavigationController ()
#end
#implementation MainNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Testing");
// Do any additional setup after loading the view.
NSMutableArray *buttonsArray = [[NSMutableArray alloc] init];
UIBarButtonItem *myButton1=[[UIBarButtonItem alloc] initWithTitle:#"button 1" style:UIBarButtonItemStylePlain target:self action:#selector(toolbarButtonPressed1:)];
[buttonsArray addObject:myButton1];
UIBarButtonItem *myButton2 = [[UIBarButtonItem alloc] initWithTitle:#"button 2" style:UIBarButtonItemStylePlain target:self action:#selector(toolbarButtonPressed2:)];
[buttonsArray addObject:myButton2];
[self setToolbarItems:buttonsArray animated:YES];
[self.toolbar setBarStyle:UIBarStyleBlack];
[self.toolbar setItems: buttonsArray animated:NO];
}
Then I make the toolbar visible in the interface builder ... the toolbar shows and the color is set in code, but the buttons do not appear
A simple solution would be to embed your UINavigationController in a custom parent view controller. This means that the navigation controller's view is a subview of the parent view controller's view. And that means that you could add another subview of the parent view controller's view, the button.

Change the title of backbutton in NavigationBar

Following the examples of the many duplicates for this questions, I can't seem to get it right.
I have a UINavigationViewController that has a LoginViewController as the rootViewController. Here I got a button with a segue (push) to a LoginInfoViewController.
In LoginInfoViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
//null
NSLog(#"%#", self.navigationItem.backBarButtonItem);
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Test"
style:UIBarButtonItemStyleDone
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
//not null, still the back button says: "Back"
NSLog(#"%#", self.navigationItem.backBarButtonItem);
}
You will need to set the backBarButtonItem of the controller you are going back to, not the controller you pushed. Move your code to the LoginViewController viewDidLoad method.
The navigation controller derives the back button for the navigation bar from the backBarButtonItem of the preceding controller in the stack. If the item is nil, it will use the value in the title property of same. If the title is too long to fit, the navigation bar may substitute the string "Back" in place of the title.
If your controller has a custom left bar button item, the navigation bar will ignore the backButtonItem property and title presenting the custom button instead.
Set the title of the back button on the view BEFORE. So, if you segue from LoginViewController, you set the back button title on the item before you segue to LoginInfoViewController
Example:
In the viewDidLoad method on LoginViewController:
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Go back" style: UIBarButtonItemStyleBordered target: nil action: nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
This means you're setting the button on the LoginViewController, not on the LoginInfoViewController.

UIBarButton added to UINavigationItem not showing up

I am trying to add a bar button to my iOS app and can't get it to show up. I can see the bar in the Navigation Item's view hierarchy by setting a breakpoint. If it helps, I chose 'Embed Navigation Controller'. Any idea what's going on?
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(choosePreferredTerm:)];
[self.navItem setRightBarButtonItem:item animated:YES];
Here is the connection in IB
This is what the embedded Navigation Controller looks like:
This is what it looks like on the sim:
Try this rather than using custom outlet "navItem" also insure your application has a navigation controller in place
self.navigationItem.rightBarButtonItem = barButton;

How to set the title of a Navigation Bar programmatically?

I have a Navigation Bar in a view, and I want to change its Navigation Item title programmatically.
How is this done?
In your UIViewController
self.navigationItem.title = #"The title";
Swift 3 Version:
If you use a navigation bar without navigation controller, then you can try this:
navigationBar.topItem?.title = "Your Title"
Hope for help.
In viewDidLoad
self.title = #"Title";
Write the below code in viewDidLoad or may be better would be under initWithNibName:
self.navigationItem.title = #"title";
Thanks.
From Apple Documentation:
The most common way to use a navigation bar is with a navigation
controller. You can also use a navigation bar as a standalone object
in your app.
So If you have a UINavigationController, all what you have to do to set the title of the navigation bar (as explained in all previous answers)
self.navigationItem.title = #"title";
But If you have a standalone navigation bar that is created programmatically within an object of UIViewController, You have to set the initial appearance of the navigation bar by creating the appropriate UINavigationItem objects and adding them to the navigation bar object stack i.e.
Create an instance of navigation bar (UINavigationBar)
Create an instance of navigation bar item (UINavigationItem) that manages the buttons and views to be displayed in a UINavigationBar object. Note that you set the title at this step.
(Optional Step) Add right/left buttons (instances of UIBarButtonItem) to the navigation bar item.
Sample of Objective-C Code for the mentioned steps:
UINavigationBar* navbar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 64)];
/* Create navigation item object & set the title of navigation bar. */
UINavigationItem* navItem = [[UINavigationItem alloc] initWithTitle:self.shoppingItem.name];
/* Create left button item. */
UIBarButtonItem* cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(onTapCancel:)];
navItem.leftBarButtonItem = cancelBtn;
/* Create left button item. */
UIBarButtonItem* doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(onTapDone:)];
navItem.rightBarButtonItem = doneBtn;
/* Assign the navigation item to the navigation bar.*/
[navbar setItems:#[navItem]];
/* add navigation bar to the root view.*/
[self.view addSubview:navbar];
For Swift version of the standalone navigation bar, check out this answer.
You can also use 👇🏻
[self.navigationController.navigationBar.topItem setTitle:#"Titlet"];
In your UIViewController's viewDidLoad
self.navigationItem.title = "The title"; //In swift 4
or
you can just
self.title = "The title"
will do the trick
you can also put the above statement in the app delegate to replicate globally.
This code did not work for me
self.navigationItem.title = #"Title here";
But this worked.
self.title = "Title Name"
Use it in ViewDidLoad method
Format :
#property(nonatomic,readonly,retain) UINavigationItem *navigationItem; // Created on-demand so that a view controller may customize its navigation appearance.
Example :
self.navigationItem.title = #"Title here";
very important note : make sure you make the changes that mentioned above in parent view Controller's viewDidLoad method, or parents navigation bar in storyboard
Sometimes you might get a case where you are updating the title and it is not causing any effect, this can be when you have a custom view on the topItem therefore you might want to update it like this: (self.navigationController?.navigationBar.topItem?.titleView as? UILabel)?.text = "My Happy New Title"

UINavigationController "back button" custom text?

The "back button" of a UINavigationController by default shows the title of the last view in the stack. Is there a way to have custom text in the back button instead?
From this link:
self.navigationItem.backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Custom Title"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
As Tyler said in the comments:
don't do this in the visible view controller, but in the view
controller that you'd see if you hit the back button
You can set the text in the Interface Builder:
Select the navigation item of the ViewController that the back button would return to:
In the utilities panel attribute inspector, enter your label for the Back Button:
I would prefer this approach over setting the title in code as in the accepted answer.
Also note, you need to do this in the view controller one level up the
stack. In other words, don't do this in the visible view controller,
but in the view controller that you'd see if you hit the back button.
--Tyler
I use this:
// In the current view controller, not the one that is one level up in the stack
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.backItem.title = #"Custom text";
}
I found a handy solution to this by simply setting the title of the controller before pushing another controller onto the stack, like this:
self.navigationItem.title = #"Replacement Title";
[self.navigationController pushViewController:newCtrl animated:YES];
Then, make sure to set the original title in viewWillAppear, like this:
-(void)viewWillAppear:(BOOL)animated
{
...
self.navigationItem.title = #"Original Title";
...
}
This works because the default behavior of UINavigationController when constructing the back button during a push operation is to use the title from the previous controller.
The title of the back button defaults to the previous view's title so a quick trick I use is to place the following code on the previous view's .m file.
-(void)viewWillAppear:(BOOL)animated {
// Set title
self.navigationItem.title=#"Original Title";
}
-(void)viewWillDisappear:(BOOL)animated {
// Set title
self.navigationItem.title=#"Back";
}
in your init method, add the following code:
- (id)initWithStyle:(UITableViewStyle)style {
if(self = [super init]) {
//...
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStylePlain
target:self
action:#selector(goBack)];
self.navigationItem.leftBarButtonItem = customBackButton;
[customBackButton release];
//...
}
return self;
}
then add a simple method, to allow viewcontroller dismissing:
-(void)goBack {
[self.navigationController popViewControllerAnimated:YES];
}
Add the following code in viewDidLoad or loadView
self.navigationController.navigationBar.topItem.title = #"Custom text";
I tested it in iPhone and iPad with iOS 9
Adding to rein's answer. Note from Apple's docs that the declaration of backBarButtonItem is this:
#property(nonatomic, retain) UIBarButtonItem *backBarButtonItem
Therefore, rein's answer will leak memory because the synthesized setter will retain the instance you pass it, which is never released explicitly. You can remedy this by using autorelease
self.navigationItem.backBarButtonItem =
[[[UIBarButtonItem alloc] initWithTitle:#"Custom Title"
style:UIBarButtonItemStyleBordered
target:nil
action:nil] autorelease]; //<-- autoreleased
Or you could point a variable at the instance so you can explicitly release it later:
UIBarButtonItem* item = ...
self.navigationItem.backBarButtonItem = item;
[item release];
Hope this helps!
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
}
I've discovered something interesting.
If you subclass the UINavigationController and override the pushViewController:animated: method and do something like this: (bear in mind that I'm using ARC)
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: #"Back"
style: UIBarButtonItemStyleBordered
target: nil action: nil];
viewController.navigationItem.backBarButtonItem = backButton;
[super pushViewController:viewController animated:animated];
Then for all ViewControllers that are pushed with your navigation controller will have the "Back" button in them automatically. If you want to change the text for certain view controllers you can try and maybe cast the viewcontroller to a certain class or your own custom protocol (which your viewcontroller inherits from which could have a method like backButtonText or something silly like that) which can give you certain information on the viewcontroller that's coming in sothat you can customize the back button text for it. Now the back button text is taken care of in a place which should hold the responsibility solely. I have to admit that creating a new button to change the text sucks, but oh well.
Can anyone think of a reason why not to do it like this? Atleast you don't have to fiddle with viewcontroller titles or have to remember to create a new back button before pushing the viewcontroller on the navigation controller.
rein's answer works well.
Note that if you push more than one view controller, the changed back button title will appear for each of them, which may not be what you want.
In that case, you'll need to create the custom UIBarButtonItem each time you push a view controller.
Also, make sure you do it before pushing the view controller, otherwise you will get a screen hiccup as the title changes.
Expanding on Aubrey's suggestion, you can do this in the child view controller:
create two variables for storing the old values of the parent's navigationItem.title and the parent's navigationItem
UINavigationItem* oldItem;
NSString* oldTitle;
in viewDidLoad, add the following:
oldItem = self.navigationController.navigationBar.topItem;
oldTitle = oldItem.title;
[oldItem setTitle: #"Back"];
in viewWillDisappear, add the following:
[oldItem setTitle: oldTitle];
oldTitle = nil; // do this if you have retained oldTitle
oldItem = nil; // do this if you have retained oldItem
It's not perfect. You will see the the title of the parent view change as the new controller is animated in. BUT this does achieve the goal of custom labeling the back button and keeping it shaped like a standard back button.
Put this into you viewDidLoad, hope it will result into what you are looking for
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Close"
style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backBarButtonItem;
[backBarButtonItem release];
if You want to set title in ARRIVING controller (sometimes more logic..)
in swift 3 do:
func setBackButtonNavBar(title: String, delay: Double){
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
if let navBar = self.navigationController?.navigationBar{
navBar.backItem?.title = title
}
})
}
in upcoming controller:
override func viewDidLoad() {
super.viewDidLoad()
self.setBackButtonNavBar(title: "back", delay: 0.3)
}
usually I put self.setBackButtonNavBar in a controller extension.
I know this is an old question and the answers' kind of out updated!
The easy way is to do this in parent ViewController:
i.e the one that takes you to next view controller.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Custom text here", style: .plain, target: nil, action: nil)
Doing this in code remove the back button style of the UINavigationConroller. If you add a Navigation Item in each of yours views, you can set the title of the back botton in the StoryBoard.

Resources