Prevent UINavigationController's navigation bar to animate? - objective-c

My UINavigationController's navigation bar is kind of static. This means, there is no back button, because going back in the stack is done via the first entry of the UITableView the controller holds. The title also always shows the name of the root item.
To achieve this I have added my own custom view to UINavigationController.NavigationItem.titleView
It looks a bit odd if a new controller is pushed in: the old navigation item vanishes, just to get replaced by one looking exactly the same.
Is there a way to prevent this behavior? I want the animation for the content of the controller, so pushing the new controller without animation is not an option.

Add your own UINavigationBar and implement your own delegate and custom animations for the content views.
It sounds like you'll only need one UINavigationItem, so that makes this model easy to manage.

Related

Why isn't my navigation bar controller handling the touchesEnded event on my navigation bar view?

This question came closest to describing my problem, but I'm missing something in the general process and the answer eventually goes into "Never mind, I figured out a different solution that isn't described".
In my case, I've got an XIB with a navigation bar and its controller. For the class fields, I've filled in my custom class names. Here's a screenshot showing the XIB, because I think this should be a relatively simple and straightforward setup...
What I want (like in link at the beginning) is for the touchesEnded event to fire so that I can do something. This works for the "view"; I can programmatically write in the event, set a breakpoint, and see that breakpoint get hit. However, my higher-level goal is to push a new view onto the app at that point -- something that I shouldn't do in the view's functionality, and which I can't do anyway because my view doesn't have access to the navigation controller (unless I do some trickery to retrieve the controller, but I want to do this cleanly).
Even though it works programmatically for the view, the touchesEnded event does not get hit for the navigation view's controller. I set it to the delegate, as shown in the image below, which I'm suspecting is perhaps only a part of what I need to do.
So now that I've set the delegate, and have seen that the touchesEnded event is being hit by the view, why isn't my navigation bar view controller picking up on the touchesEnded event? Am I mistaken and should instead be figuring out how to push a new view from the navigation bar's view, since I've seen that THAT touchesEnded event is being hit? It just seems like something I should be handling in the navigation bar view's controller, but I can't get that controller's touchesEnded event hit.
Thanks!
It's not clear from your post, but it looks like you're adding a navigation bar to your app explicitly, is that true? If your controller is embedded in a navigation controller, then there's no need to do that. You can add a view to the navigation bar, and add a UIImage view as a subview. If you set user interaction to be on, and add a tap gesture recognizer to the image view, you should be able to get the effect you want.
Then you have to override UINavigationBar, and override becomeFirstResponder, returning YES.

addSubview: re-writes the navigation stack?

I'm working on a app which uses the controller containment pattern as described in the View Controller documentation in the iOS SDK.
I've written the controller container, and it works great. My controller is basically containing two sub views and it displays them both at the same time, sliding one over the other depending on what the user is doing. Works wonderful.
Now, I want to use this container controller in a navigation view. This is to get push segues to work. In effect, from my contained controllers, I want to be able to use the navigation stack, push a new controller on, and pop when the user is done.
However, I have noticed that if the navigation view is instantiated with my container controller as the root container, things fall apart.
In particular, I have noticed this:
In the iOS documentation, container controllers call addChildController: and then addSubview:. This seems to break the navigation stack, as the push segue does not work - it behaves like modal. I believe it does this because addSubview resets the navigation stack.
I confirmed this by replacing addChildController and addSubview with [self.navigationController pushViewController...]. I confirmed it is a problem with addSubview because I can reproduce the issue when I omit the call to addChildController.
When I do this, the navigation stack works properly. But of course, my container controller does not, as only the "most recently pushed" controller is visible.
I'm doing this because in my contained controllers, I want to push a new controller onto the stack, and when the user is done, I want to "pop" the stack, without reloading the "previous controller".
Using a modal segue reloads the previous controller; using a push controller does not.
I cannot find any documentation on the behavior of addSubview and it's effect on the navigation stack.
Thank you in advance for any light you guys can shed!
I'm having a bit of trouble completely understanding what you are doing, but I think that what you want to do is exactly what I'm doing.
I have a UINavigationController that has as its rootView a container UIViewController. That controller adds children per the normal methods. One of those children views pushes other views that may get popped.
One of those pushed views COULD message the appDelegate and make itself the rootViewController if it wanted to. In general, as long as you keep a strong reference to a view controller, you can remove it from whoever 'owns' it, and muck around with the navigationControllers viewControllers array to your hearts content.

Reference to source view controller and destination view controller at the same time

I have a series of UIViewControllers throughout my application. Most of them have the navigation bar but some of them hide it.
The problem is that sometimes as you transition between a view with or without navbars to another view with or without navbars there is a black box that replaces the navbar during the transition. This problem was discussed here: Hiding a UINavigationController's UIToolbar during viewWillDisappear:
This solution is fine and it does get rid of the black box, but I really don't want what was described as a "Cheshire Cat" disappearance. I've tried myriad solutions using prepareForSegue, ViewWillAppear, viewWillDisappear, etc. The best I can do is change the scenario in which the black bar shows up.
By this I mean, there are four combinations of view transitions between the two navigation bar states (hidden vs. not-hidden):
Hidden - Hidden
Hidden - Not Hidden
Not Hidden - Hidden
Not Hidden - Not Hidden
No matter what solution I've tried, at least one of those combinations results in my black box rearing its ugly head. The problem I have is that I've been unable to find anywhere that I can get a reference to the source view controller and the destination view controller when popping a view off of the navigation controller's view stack.
If I could get both references in the same event, I could simply determine what the combination is and handle the behavior appropriately like I would in prepare for segue.
Now, I know that "it's not possible" is a reasonable (and even a probable) answer, but I won't accept that as a solution alone. If it is indeed not possible, I'd like thoughts on a reasonable alternative. For example, I could handle all view controller popping manually (including the default back button) and thus could get the "upcoming controller" from the navigation controller's stack.
I would just prefer a solution using built in APIs or at least a solution where my controllers didn't have to be aware of their own navigation bar states.
Thanks a lot,
Patrick
I think UINavigationControllerDelegate is what you're after. It declares two methods:
-navigationController:willShowViewController:animated:
-navigationController:didShowViewController:animated:
All you need to do is set yourself as the delegate of the parent navigation controller and implement these methods to be notified of incoming view controllers.
Having said that, I've never needed to resort to this for hiding and showing navigation bars. Strictly speaking, view controllers where the navigation bar will always be visible never touch the navigation bar's visibility. When I'm moving into a view controller where it needs to hide, that view controller is responsible for hiding and setting it back to its prior state before disappearing. Following these standards has proven reliable for me.

Is there a way to change Views in iOS without using UINavigationController?

I have a login page at the beginning of my app that I do not want on the view stack. Is there a way to load my first post-login view after the login without using UINavigatorController?
Is there a better way to be doing this? Should I be using 2 UINavigationControllers? Is there a way to change the RootViewController for a UINavigationController?
Yes, you can change root controller of window. Set window's property rootViewController to new controller and you're done. Don't forget though that first controller (one you are removing) will not receive viewWillDisappear: and viewDidDisappear: messages. Send them yourself before switching controllers if you're interested in them.
You might also look at UIViewController#presentViewController

Why does the iPad stop auto-rotating when I start overlaying View Controllers?

I have a fairly hefty project, where I am loading a few view controllers, one after the other. First, a splash screen, followed by a menu system, and when the user clicks on the menu it goes through to an article view controller.
Putting all these in with shouldAutorotate... set to YES for all rotations, this works fine. However, I have a menu bar I need to slide down over the top when a tap gesture has been recognised. I have one for the main menu, and one for the article view.
If I put one of these in, it still auto-rotates fine. However, as soon as I put the next one in, the auto-rotate stops working. I've tried putting the menu bars in the app delegate, as well as nesting them inside the menu/article view controllers. The Menu Bar view controller also has shouldAutorotate... set to YES. In fact, every single view controller in the project (all 7 of them) have it set to YES. And yet, when I add my second Menu bar controller, it stops auto-rotating. It doesn't even trigger the "shouldAutorotate" method to ask it.
The code is way too large to post here, but if you'd like to see anything in particular then just ask. I'm totally stumped! I'm about to pull the menu bars out of their view controller and code them up in each of the view controllers individually. This will be a hideous amount of code duplication, but I can't think of any other way round it!
Any ideas? Thanks!
The answer appears to be... Don't put view controllers within other view controllers! One view controller = one screen, seems to be the rule. I have a lot to learn!