What is best approach to add back button for first view controller in navigation controller? - ios7

I'm beginner iOS developer, so don't know how to solve my problem correctly. I have one navigation controller and want to make modal transition to another navigation controller that will have back button on it's first view controller.
In my first navigation controller I made this:
InfoViewController *destinatinViewController = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle:nil];
[self presentViewController:destinatinViewController animated:YES completion:nil];
InfoViewController is UINavigationViewController.
Then I made this in InfoViewController (second navigation controller):
InfoRootViewController *rootViewController = [[InfoRootViewController alloc] initWithNibName:#"InfoRootViewController" bundle:nil];
[self pushViewController:rootViewController animated:NO];
For now I know how to add button to go back, but it has not styling (certainly arrow). As I understand because it is only one view in stack of second navigation controller.
So, I need your help to add styled back button for first view controller of navigation controller, because I don't want to make own styling (I'm lazy).
Thanks, for any advance!
PS: I made modal transition because, it has animations like from bottom or top. I tried to use custom animations for pushViewController, but in iOS 7 they're working not correctly.

I'll let someone else help you with the back button issue because I think it's a mistake to create one for a modal view controller that's presented from the bottom of the screen. Typically, such a modal view controller is dismissed with a cancel button or its equivalent. If you really think that you need a back button then you should probably push the view controller onto the existing navigation stack instead of presenting it modally.
However, I am happy to show you how to properly alloc/init a navigation controller and then present it.
I don't know why you're subclassing UINavigationController, but I'm going to pretend that you don't need to (which is probably the case).
InfoRootViewController *rootViewController = [[InfoRootViewController alloc] initWithNibName:#"InfoRootViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[self presentViewController:navController animated:YES completion:nil];

Related

What is the design pattern for navigating between ViewControllers?

I currently have 1 storyboard which contains 2 view controllers: ViewController and TableViewController. The ViewController is the login view, and the TableViewController is the page that displays results (results view).
Currently, I did not create a segue from the login view to the results view. Instead, on the login view, after a user presses the login button and is authenticated, I programmatically push to the results view as follows.
XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController pushViewController:controller animated:YES];
Indeed, the results view shows, but there is a "< Back" button at the top left, which, if pressed, goes back to the login view.
So, my question are:
How do I get rid of the login view from the view stack? (so the back button on the results view does not show)
Is this "programmatic" way of navigating between views "bad"? Meaning, should I rely on the storyboard and segues instead? Should I navigate to a new storyboard (I've seen this question asked on SO, though I haven't visited it yet)?
I'm a newcomer, so any help is appreciated.
If you don't want to use the navigation stack, you have to use presentViewController instead of pushViewController
XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
[viewController1 presentViewController:controller animated:YES];//viewcontroller1 is current view controller
Never use the code below unless you want to have the navigationController stack in viewController you are showing
/*XYZResultsTableViewController* controller = [[XYZResultsTableViewController alloc]init];
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController pushViewController:controller animated:YES]; */
for more information on this difference between presentViewController and UINavigationController?
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html

Does presentModalViewController: add the view controller to the stack?

I have a main navigation controller with a root view controller. In the root view controller, on the push of a button I present second view controller like this:
SecondVC *secondVC = [[SecondVC alloc] initWithNibName:#"SecondVC" bundle:nil];
[self.navigationController presentModalViewController:secondVC animated:YES];
In the second view controller, on the push of an other button, I want to present a third view controller (this time from a Storyboard):
ThirdVC *thirdVC = [[UIStoryboard storyboardWithName:#"Settings" bundle:nil] instantiateInitialViewController];
[self.navigationController presentModalViewController:thirdVC animated:YES];
However this doesn't do anything. I debugged and it turned out, that self.navigationController is nil.
Shouldn't it be the main navigation controller? Or doesn't presentModalViewController: add the view controller to the stack? Do I always have to put a view controller in a navigation controller before presenting id modally?
The new view controller SecondVC is being presented modally, and it's not added to the view controller stack of the navigationController. You need to create a new UINavigationController, and put SecondVC inside the navController before presenting it modally.
You'll need to add something like:
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController:secondVC];
[self addChildViewController:navController];
[self.navigationController presentModalViewController:secondVC animated:<#(BOOL)#>]
your view controller while being presented is not inside a navigation controller. And will not have access to the presenting controllers navigation controller.
Furthermore if you push or pop stack items on the navigation controller beneath the modal view controller you will likely not notice anything.
If you want to put the controller in the stack you can alternatively show the view controller yourself.
[self.view addSubView:myViewController.view]
myViewController.view.frame = self.view.bounds;
and to dismiss the view controller you would simply remove it from its superview.
the drawback here is that some of the did and will appear methods are not called on the view controller. Therefore you may want to call them yourself.
But the principal is much the same. And you can easily simulate the presenting animation with the animation system.
Give it a starting point below your form, then start your animation block and put the view.frame to superview.bounds also giving it an animation time. I find that 2 seconds is ok. sometimes less.
at this point the presented view is inside the controller which is on the stack. Now while you cant directly modify the navigation controller within the presented view controller you could set a delegate that tells the original your intentions and therefore the presenting view controller (the one on the navigation stack) can push or pop the view controllers as requested. And the presented view controller will be pushed along with it.
Another positive point is that you can do much like other apps do, and present a semi modal view. With a partially transparent background. this way you can show things happening behind the view even tho they dont directly manipulate it.

How to go back to previous view in Objective-C?

I am a beginner in iOS programming and I want to implement the functionality of going back to home view.
I have use this code:
-(IBAction)onclickhome:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
I have used navigationController in home button click event but it is not jump to home screen.
Do you have any suggestion and source code which applies to my code?
I'm not sure I understand your question.
What do you mean with
I have used navigationController in home button click event but it is
not jump to home screen
?
If you want to pop to the root controller you can use popToRootViewControllerAnimated.
[self.navigationController popToRootViewControllerAnimated:YES];
From Apple doc of UINavigationController
popToRootViewControllerAnimated:
Pops all the view controllers on the stack except the root view controller and updates the display.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
If you have set up a UINavigationController and its root controller is called A, then if you navigate from A to B and then from B to C you have two possibilities to come back to a previous controller (you can have others but I list the main ones):
navigate back from C to B with popViewControllerAnimated
navigate back from C to A with popToRootViewControllerAnimated
The best way to navigate back and forth views is by pushing and popping views from navigation view controller stack.
To go one view back, use below code. This will ensure that the smooth transition between views are retained.
UINavigationController *navigationController = self.navigationController;
[navigationController popViewControllerAnimated:YES];
To go two views back, do as below
UINavigationController *navigationController = self.navigationController;
[navigationController popViewControllerAnimated:NO];
[navigationController popViewControllerAnimated:YES];
If you aren't going back to your expected view, execute below code before popping any of the views...
UINavigationController *navigationController = self.navigationController;
NSLog(#"Views in hierarchy: %#", [navigationController viewControllers]);
You should see an array like the below one, which will help you in verifying the stack is maintained as expected.
Views in hierarchy: (
"<Main_ViewController: 0x1769a3b0>",
"<First_ViewController: 0x176a5610>",
"<Second_ViewController: 0x176af180>"
I use
[self dismissViewControllerAnimated:YES completion:nil];
since others answers didn't worked in Xcode 8.0

Several Navigation Controllers in an app

I have an app with navigation controller, but my app also has a simple separate view which is not a navigation controller part. And what I want to do is to add a brand new navigation controller to this view.
For my first navigation controller I used this code in my AppDelegate:
UINavigationController *navigationController = [[UINavigationController new] initWithRootViewController:viewController1];
navigationController.viewControllers = [NSArray arrayWithObject:viewController1];
self.window.rootViewController = navigationController;
But which code I should use, if I want to create a new Navigation Controller ?
Thanks !
UPDATE:
So, I made some pictures:
One the first pic there is a navigation controller (which is declared in AppDelegate). And It contains an info button. Then, when we press the button we move to another view (pic 2). And its just a navigation bar in this view, not an navigation controller. I wanna add a navigation controller, not a navigation bar in this view, so users will be able to use UITableView easily
We would need to know a little more about your intended view hierarchy, and application flow. But in the code you're posting, I'm not sure what is going on. Why not just:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController1];
self.window.rootViewController = navController;
That said, you would create other UINavigationControllers exactly the same way.
Update:
When you press the info button on the first view, you could present the navigation controller modally I think.
- (IBAction)infoButtonAction:(id)sender;
{
// InfoTableViewController is the controller with Instructions, Contact, and something else
// my Russian isn't so good.
InfoTableViewController *tableController = [[InfoTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableController];
navController.modalPresentationStyle = UIModalPresentationFormSheet; // or whatever
[self presentModalViewController:navController animated:YES];
}
Note that I'm not dealing with memory management because I don't know if this is ARC or not. Is that how it should behave?

loading a UINavigation controller from a UIView

i am designing an app that has a login screen. it is a UIView with username/password and a button to submit. once the user authenticated successfully, i want to load a new xib file that holds a navigation controller and a navigation bar. below the bar i want to load a tableView and switch between other views as i move along with the programming of it.
what i did is create a new class that inherits from UINavigationController and assembled the xib file to include the navigation controller. i hooked it back up to file's owner and i'm loading the navigation controller modally like this:
myNavController* navVC = [[myNavController alloc] initWithNibName:#"navXibFile" bundle:nil];
[self presentModalViewController:navVC animated:YES];
[navVC release];
this works okay as the navigation controller shows up. however, it shows up with no title, even though i've set one up in IB. moreover, the tableView's delegates are hooked up via IB but i cannot even see empty lines. all i see is an empty navigation bar at the top and blank view (one piece) below it.
thank you for your help.
so i figured it out... first it's a design decision right? is the app being managed by a navigation controller? if so (which is my case), expect the main (first) view, that is a login page, all you need to do is to hide the navigation bar in your ViewdidLoad for the main view:
[self.navigationController setNavigationBarHidden:YES animated:YES];
once the user logs in and you push the next view like this:
MainTableViewController* mainTableVC = [[MainTableViewController alloc]
initWithNibName:#"MainTableViewController" bundle:nil];
[self.navigationController pushViewController:mainTableVC animated:YES];
[mainTableVC release];
and lastly, in the ViewDidLoad of the next view controller:
[self.navigationController setNavigationBarHidden:NO animated:YES];
in case your app needs a navigation controller for a specific section of the app but not all if it, you will need to use the VC to manage this, in a similar way the appDelegate manages the sample navigation based sample app.
i hope this helps anyone struggling with wrapping their minds around the design patterns implemented here.
cheers.