How do you use Interface Builder to control UINavigationControllers properly? - iphone

I have been in the process of learning to build iPhone applications for the last two weeks. I've gotten through a fair amount of content, and now I'm trying to create a modal pop up with presentModalView.
I can can successfully create and slide up a view, but I notice that modal views don't provide you with a default navigation bar at the top of the window, which makes sense for flexibility I guess. Most modal views I've seen have a "Cancel" and a "Done" or "Save" button as navigationItems on what looks to be a UINavigationController. My thought then was just to instantiate a navigation controller and push the single view onto the view controller stack, and presentModalView:navController.view ...
Because the view is relatively complex, I was trying to lay out both the UINavigationController, with the bar buttons, and the view I was hoping to push onto the stack in a single xib -- no matter what I try, I can't seem to get the linkages correct. Can you even do this? Or should I create a separate class/xib for the view I'm going to be pushing onto the navigation controller? Seems like a lot of classes and files for one screen, so my feeling is I must be missing something.
At this point, I could have done it programmatically about an hour and a half ago... however, this is a real nag, since IB seems GREAT for some things. Anyone have an experience with a situation like this?
Thanks,
Josh

If you're not going to use this new XIB for navigation, there's no point in making a navigation controller.
In interface builder, simply drag a UINavigationBar to the top of your view, and add a "Done" Button. Now, add an IBAction to the done button to dismiss the view controller. Your ViewController code for the dismiss IBAction should look something like this:
-(IBAction)dismiss {
//Any logic before dismissing the modal view
[super dismissModalViewControllerAnimated:YES];
}

Related

What is the proper way to create a segue to a new View without putting it on current UINavigationController's stack?

I'm trying to create an app using storyboard which has 4 scenes:
ChooseLoginMethod
EnterLoginData
SuccessfulLogin
MainScene.
What I'm doing right now is the following: I have an UINavigationController which has ChooseLoginMethod as its root view. ChooseLoginMethod has several buttons (for different login methods) which are push segues to EnterLoginData. EnterLoginData has a push segue to SuccesfullLogin and SucessfullLogin has a push segue to MainScene.
The problem is that SuccessfulLogin and MainScene display the back button on the top bar, which makes no sense for the application.
I've tried:
Hidding the top bar on these two Views. Not successful.
Changing the segue to modal. Seems to work, but doesn't feel like the right thing to do.
So what I would like to do is create a segue which breaks the chain of Views which are on the UINavigationController's stack. Is there a proper way to do this in storyboard?
-- edit --
Maybe what I should do is replace the root view ( Set root view for UINavigationController ). This may work, but seems like a programming work-around for something that should be possible to be done in storyboard. Or maybe it is just me not getting the "iOS way of doing stuff".
You had to use setNavigationBarHidden before the viewcontroller appears on the screen, like in viewWillAppear.
But then you can't go back from "MainScene" to the "RootController". So you should do something like popToRootViewController after "SuccessfulLogin" and then pop "MainScene".
I think it's usually best to have your main scene be the root view controller. From its viewDidAppear method, you can present your ChooseLoginMethod controller modally, and from there do modal transitions to your other login controllers. When you get to the end, and you want to go back to the main scene just dismiss the modals from the root view controller -- this will dismiss the first one, and any that were presented from it:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];

Creating a custom view to replace UINavigationBar

I've had a lot of experience customizing UINavigationBars and find it is a royal pain in the a** to get it to do what I want without a lot of effort. So I've written my own custom UIView that behaves just like a UINavigationBar and is fully and easily customizable. However, I am having a problem, when the Navigation controller pushes a new controller onto the stack, my custom view stops receiving touch events.
To make this more clear, my app loads and displays a view controller, in the viewDidLoad method, I create and add my custom nav bar to the controller's view. A navigation controller is created programmatically and a view controller is pushed to it. At this point my custom view is on top and receiving touch events. When I push another view controller to the navigation controller's stack, my custom view is still on top and visible, but not receiving events.
So my question is how to I get my custom nav bar back into the responder chain?
Thanks for your help!
If you don't have to support iOS < 5.0 you should try to add the UINavigationBar using UINavigationController's - (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass method instead of doing it manually.

Memory issue in Present Modal View Controller

I am just presenting modal view controllers one after the another and not dismissing that. Because my requirement is such that I want show view controllers one after the another like chain.
1) Will this create memory problem ?
2) If so what is the work around ?
Thanx in advance
Yes you may get a memory or performance problem. I don't think Apple intended/intends for anyone to present multiple modal view controllers one after the other.
Have you seen this : Problem dismissing multiple modal view controllers
I think you should dismiss the current modal before presenting a new one. Always. Always. Always. You don't have to dismiss them animated though, you can dismiss them without animation so you don't see them disappear visually.
If you need to be able to go backwards through the chain of modally presented view controllers then I would instigate a method for doing this. e.g. add properties to your UIViewController subclasses that specify the next and previous viewController (or maintain a history trail of the viewControllers).
To be honest, it sounds like you should be using a navigationController and not presenting the viewControllers modally.

Fixed UIToolbar and slideup UIViewController panels, over a UINavigationController

I am looking to create a UINavigationController iPhone app with some UI that, as far as I can tell, is slightly strange. Despite my best efforts to figure out a good solution to this problem, I can't seem to find the right solution, so would appreciate some advice.
There will be a (customized) toolbar at the bottom with several buttons. When a button is pressed it will present a modal panel view, which slides up, closing other open panels, but leaving the toolbar visible. When the same toolbar button is pressed again the modal view slides down again. The modal views are used to choose a new UIViewController to push onto the UINavigationController. These modal slideup-panels can also be opened by buttons in the controllers that have been pushed onto the UINavigationController.
The main problem, as far as I see it, is presenting and dismissing the modal UIViewControllers so that the toolbar remains. Also - who does the presenting/dismissing? The App Delegate or the root ViewController, or someone else?
My initial (bad) solution was to have a root UIViewController that had a sub-UINavigationController whose view was used as a subview, and the toolbar & modal panels were just other subviews. But, for pre-iOS5 apps, sub-ViewControllers are bad and sick and wrong and evil (no matter how logical they seem).
Another (probably bad) option is to use a UINavigationController subclass as the root view controller, and have this handle all the toolbar functionality.
Any suggestions? Am I overlooking some obvious in-built functionality or a standard design concept?

View Hierarchy, UITabBarController, adding more views in certain tabs

So I'm not sure what is the best way to do something, or the preferred way. Here's essentially what we are trying to do:
-UITabBarController as the root
-first tab is a FruitViewController
-FruitViewController can push an AppleViewController (not sure if push is the correct word, but basically go to the next viewController)
-AppleViewController has a back button in the UIToolBar to return to FruitViewController
-second tab is VegetableViewController
-VegetableFruitViewController can push CeleryViewController
At the end of both ViewControllers, you can push another ViewController called CalorieViewController. My question is that what's the best way to present view controllers per tab? Since I want both tabs to use CalorieViewController, in order to reuse it, I'm assuming I need to keep it non-coupled with the other ViewControllers.
The way my coworker implemented is, on each tab, all ViewControllers for that tab are created and added as a subview. Based on the button pressed, it hides and shows the other view. This seems like not a good idea. It seems like presentModalViewController, and dismissModalViewController (for the back button) might work, but I'm not sure if that's the preferred method.
I would suggest you make the root view controller for each tab a UINavigationController, with the view controller's that are currently set for the tabs as the root view controller of the navigation controller. That way you can push and pop views all you want. UIViewController even has support for automatically pushing the tab bar off the screen when pushing a new view controller onto the stack.