What's the difference between UINavigationController and UINavigationItem - ios

I don't understand what is the difference between
self.navigationcontroller.navigationitem and self.navigationitem
i have navigation based application and in viewDidLoad method in rootViewController of navigationController I set the NavigationItem titleView to custom image by using this code
UIImageView* titleImage=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
self.navigationItem.titleView =titleImage;
by the way if i try to change titleview by this way
UIImageView* titleImage=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
self.navigationcontroller.navigationItem.titleView =titleImage;
nothing was happened.
, and when navigationcontroller pushed the another view to the stack the titleview of navigationitem is cleared and reference sets to nil, and also i noticed that the references of self.navigationcontroller.navigationitem and self.navigationitem are not the same.

I believe what you are asking is the following: self.navigationController.navigationItem and self.navigationItem. I am ignoring the rest of the question since it is not really essential to the question.
From what I understand self.navigationController.navigationItem is useless since it is accessing navigation item of the navigation controller (ie your rootViewController).What you really want is self.navigationItem, navigation item of the view controller because that is what essentially going to show up in your view controller.
UINavigationController is a subclass of UIViewController so self.navigationController.navigationItem is just a spillover method from subclassing. It does not do anything positive (at least in my experience).
Edit: Read this for further clarification.

They are Different. If you dynamically add UINavigationController, then you use self.navigationController.navigationItem.
Please better clarify your question.

Related

Two UINavigationItems?

Could anyone explain why there are two navigationItems? When I log like below:
NSLog(#"%#", self.navigationItem);
NSLog(#"%#", self.navigationController.navigationItem);
I get two different instances of UINavigationItem:
<UINavigationItem: 0x7f85b06f5a20>
<UINavigationItem: 0x7f85b06ab640>
I have only created a UINavigationController programmatically once.
All UIViewControllers have a property navigationItem. Therefore, because UINavigationController is a subclass of UIViewController, it also has this property.
self.navigationItem will be the one presented when your controller is pushed. The documentation for navigationItem, it's clear about this property
This is a unique instance of UINavigationItem created to represent the view controller when it is pushed onto a navigation controller.
self.navigationController.navigationItem would be the item displayed if Apple allowed UINavigationControllers to be nested. However, since this isn't allowed, it's best to forget about it.
Okay, this question puzzled me for awhile but I think I figured it out. self.navigationItem and self.navigationController.navigationItem are two different objects. Here's why:
In iOS, each UIViewController object has a UINavigationItem. The navigationItem for your current view controller is self.navigationController, and self.navigationController.navigationItem is kind of a spillover object, it's the navigationItem for your parent navigationController.

UIBarButtonItem in custom UINavigationController not showing up

On my side menu I call a NavigationController for each item on didSelectRowAtIndexPath.
Because of that I have a few NavigationControllers. So I created a custom UINavigationController to reuse the code.
The thing is that my UINavigationController subclass is being called but nothing appears on the simulator.
[self.sideMenuViewController setContentViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"EventsXib"]];
EventsXib is my CustomNavigationController
Any idea?
For the record, the whole point for me to do this is that I want the same leftBarButtonItem and 2 rightBarButtonItems on all my ViewControllers.
UPDATED:
I noticed that this actually worked:
self.navigationItem.leftBarButtonItem = self.navigationController.navigationItem.leftBarButtonItem;
self.navigationItem.rightBarButtonItems = self.navigationController.navigationItem.rightBarButtonItems;
But I still have to do this in every viewController, and thats not what I want.
Here is a general idea of what it looks like:
As #GoGreen suggested, I created a base view controller with the corresponding buttons on the navigationItem.
Its not the simple solution I had in my mind but it works pretty good.

explain the navigationItem property of a UINavigationController

when i read the api doc of the UINavigationController,the property navigationItem,has a tip:
Avoid tying the creation of bar button items in your navigation item to the creation of your view controller’s view
i don't understand what does this mean,can anybody explain this in detail
This was probably added to the documentation quite recently as I stumbled across this today for the first time. Moreover, in nearly every sample code that I've seen the initialization of the bar buttons happens in the viewDidLoad method - which is obviously not the best place to do this according to the quoted statement.
What Apple says us with this is that there can be situations where the content of the navigationItem is requested when the viewDidLoad method is not executed yet or not gets executed at all.
This happens when you push more than one viewcontroller at once. E.g. by using the setViewControllers:animated: interface or by doing something like this:
ViewController1 *firstViewController = [[ViewController1 alloc] init];
ViewController2 *secondViewController = [[ViewController2 alloc] init];
[navigationController pushViewController:firstViewController animated:YES];
[navigationController pushViewController:secondViewController animated:YES];
In this case the viewDidLoad method of firstViewController will not be called until the user navigates back to it. If you have set the title property in firstViewController, you would expect to have the back button labelled with the title you set in firstViewController. However the back button will be called "Back", as the title property of firstViewController is nil when UINavigationController asks for it.
The conclusion is: Tying the creation of bar button items to the creation of the view works for most situations. Nevertheless keep in mind that you can have situations where you need the navigationitem information before or without creating the view. In this case consider initializing the navigationItem property in the viewcontrollers init method.

Add image UIBarItem to UINavigationController or alternative

I have a UINavigationController with a left and a right button on an app being used as a remote control for a piece of hardware. I would like to show that the hardware is connected to the app by displaying an icon in the navigation bar to the left of the right button. From the documentation it looks as though I can only add UIBarButtonItems which make me suspect there is another, more conventional place for my 'connected LED' indicator.
So my question is can I display an icon in a UINavigationController navigation bar and if not where should I display it?
UINavigationBar is a subclass of UIView, so you can add items to it like this:
[navBar addSubview:whatever];
The navigation bar is a property of the navigation controller (i.e. you can reference it like this self.navigationController.navigationBar).
There isn't really a "conventional place" for something like this. :)
I suspect this 'connected LED' should be displayed on all views, regardless of the current view (and its UINavigationItem). If that is correct, the easiest way would probably be to NOT put that icon in the actual UINavigationBar, but place it as a separate UIView in the UINavigationBar's superview.
you should be able to just create a uiview programatically and add it as a subview of the navbar
UIImageView *connectedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"connected-icon.png"]];
[self.navigationController.navigationBar insertSubview:connectedView atIndex:0];
[connectedView release];
if insertSubview doesn't work as you expect try addSubview:
[self.navigationController.navigationBar addSubview:connectedView];
You probably want to create the connectedView as a property though so you can (more) easily remove it when you are no longer "connected".
see this other examples of the approach
try this code
[[[yourViewController viewControllers] lastObject] navigationItem].titleView = yourImageView;
worke for me in customising navigation bar in mail controller. Hope you get some idea from here.

How to remove itself and superview from super superview?

I have a UIViewController classes A and B. A loads B using: [A.view addSubView B.view].
B has a navigation bar with a Back button. I want to go back to A when I click it, so in the selector I tried [self.view removeFromSuperview], but it only removed the navigation bar. Then I tried [self.view.superview removeFromSuperview], it still just removed the navigation bar. What should I do?
Also, another minor issue with the Back button: setting it's title. I tried these two ways, but it still displays "Back".
navItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Chapter" style:UIBarButtonItemStylePlain target:self action:#selector(handleBackBarButtonItem:)];
navItem.backBarButtonItem.title = #"Chapter";
Thank you in advance!
I don't think you quite understand how navigation (with UINavigationController) works in iOS. Assuming you want animation, this is what you want:
Set up a UINavigationController. This can be done in the app's delegate (to avoid memory leakage, set an instance variable on UINavigationController *navController:
navController = [[UINavigationController alloc] initWithRootViewController:A];
Note that we are adding A as our root view controller.
Push the second view controller when needed. I assume that you are adding B.view after a button is clicked or something. In the implementation of the method that adds the second view controller, run the following code, instead of [A.view addSubview:B.view]. This method should be in the first controller's .m file:
[self.navigationController pushViewController:B animated:YES];
This will also give a nice transition effect.
Pop the second view controller off the stack. With UINavigationController, a pretty arrow-shaped back button is automatically included in a pushed view controller, to navigate back to the last view controller. This means that you don't even need any code to allow backward navigation.
That's it! Now if you need to change the title of B's back button, do this in A's viewDidLoad method:
self.navigationItem.backBarButtonItem = customBackButtonItem;
You can get an array of subviews and then remove the ones you wanted to be removed. This SO post will show you how to remove all subviews or multiple subviews using subviews array.

Resources