I am using the PKRevealController that gives the side menu functionality to an application.
I Have UIbuttons in the side menu and they trigger a view to be pushed on the navigation stack. However, Each view being pushed has a back button that leads to the navigation view controller.
What would be the correct way to make sure that each view pushed onto the stack will become the root of the navigation stack? Except obviously not view controllers that I need to stack.
You can make it any view controller as the root view controller of the navigation controller for example
You can try this.....Just replace this code in FrontView controller didSelectRowAtindexPath
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
self.navigationController.viewControllers = [NSArray arrayWithObject: [[LeftDemoViewController alloc]init]];
If you are not going to push view controllers, you may prefer to have a main view, which contains the view of the current view controller. Everytime you change to another app section you remove that view, and insert the view of the new viewcontroller.
But if you prefer to have a navigation stack you can remove the previous viewcontroller from the navigation stack and add the new one. Assuming you will only have one view controller at the same time and you are using a tab bar controller
UIViewController * root = nil;
UINavigationController *rootNavController = [[[UINavigationController alloc]initWithRootViewController:root] autorelease];
[root release];
NSMutableArray * viewControllersArray = [NSMutableArray arrayWithArray:self.tabBar.viewControllers];
[viewControllersArray removeObject:[viewControllersArray lastObject]];
[viewControllersArray addObject:rootNavController];
[self.tabBar setViewControllers:viewControllersArray animated:NO];
If you want to have more than one, instead of removing the last one all the time you will have to remove the first one. So you will have to replace lastObject with objectAtIndex:0 and addObject with insertObject:atIndex:0
Hope it helps
Related
I have my first NavigationController set up with root viewcontroller - PhotoViewController, It's a collectionView with grid of images. When image is selected I wan't to present a second navigationController with root controller - DetailViewControler.
My first navigationController is set up in appDelegate. I really don't understand how and where should I create the second. I'm not using IB. At the moment I have this in my DetailViewcontroller viewDidLoad:
DetailViewController *detailView = [[DetailViewController alloc] init];
self.detailController = [[UINavigationController alloc] initWithRootViewController:detailView];
But when i'm trying to push a new controller, nothing happens. I guess that my code is in wrong place.
When I try to present second controller modally from my PhotoViewController, I have an error(trying to present nil viewController).
The common idea is to have a single navigation VC that contains -- and lets you navigate between -- other VCs. In the situation you describe, you wouldn't create another navigation VC. Instead, create just the detail VC and push that onto the existing navigation VC...
// assuming self is a view controller contained by a navigation controller
self.detailController = [[DetailViewController alloc] init];
[self.navigationController pushViewController:self.detailController animated:YES];
Use a parent view controller as your initial view controller and add the navigation controllers as children, then transition between them. See this blogpost that I wrote: http://sketchytech.blogspot.co.uk/2012/09/container-view-controllers-parent-view.html
In android, switching between activities, is fairly straightforward
you call
Intent intent = new Intent(this,NextActivity.class); <- define the next activity
startActivity(intent); <- start the next activity
finish(); < -get rid of the current activity
now in iOS i know how to do this:
UIViewController *nextviewcontroller = [[UIViewController alloc]initWithNibName:#"nextvc" bundle:nil];
[self presentViewcontroller:nextviewcontroller animated:YES completion:nil];
How do I get rid of the current view controller? so that currentviewcontroller dies after presenting nextviewcontroller ?
[self dismissViewController:YES]; doesnt seem to do the trick
the lifecycle methods viewWillDisappear and viewDidDisappear are called even if I don't call [self dismissViewController:YES];
i want "currentviewcontroller" to be removed from the memory, and from the viewcontroller stack, so that clicking "back" in "nextviewcontroller" will go to some thirdviewcontroller that was before currentviewcontroller
In iOS is different, since there's no concept of Activity and everything is more focused on the app itself (in Android you can mix activities from different apps). Therefore, there's no concept of "view controller stack".
The most similar concept is the "navigation stack" of navigation controllers, where you actually push and pop new view controller into some kind of linear navigation. A navigation bar is automatically created and populated with back buttons.
presentViewController will show your view controller modally upon the current one, but you can't thrash the presenting one since it's holding and containing ("defining context") the new one.
If you use a navigation controller for your navigation hierarchy (I don't know if you can), you can override the back button and use something like
UIViewController * prev = self.navigationController.viewControllers[self.navigationController.viewControllers.count -2 ]
[self.navigationController popToViewController:prev animated:YES]
With a modal view controller, you may try something like (I haven't tried but it may work)
[self.presentingViewController.navigationController popViewControllerAnimated:YES]
You should write one of these code into the target action of your close button.
iOS doesn't maintain a global stack of controllers in the way that Android does. Each app shows a controller at its root, and that one is responsible for showing the other controllers in the app. Controllers can display other controllers modally using presentViewcontroller:animated:completion: but the presenting controller remains underneath the presented one.
If your current controller is the root controller, then instead of using presentViewcontroller:animated:completion: you'd just do this:
self.view.window.rootViewController = nextViewController;
It's very common for the root controller to be a UINavigationController, which does manage a stack of controllers. If that is the case, and if your current controller is at the top of the stack, you'd do this:
[self.navigationController popViewControllerAnimated:NO];
[self.navigationController pushViewController:nextViewController animated:YES];
If your setup is different, you'd do something different; it's hard to say what without knowing more. But it's most likely that you'd be in the UINavigationController case.
In the viewDidAppear of your nextviewcontroller you could add :
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSArray *controllers = self.navigationController.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:controllers];
[newViewControllers removeObjectAtIndex:[controllers count]-2];
self.navigationController.viewControllers = newViewControllers;
}
There is nothing available like this in iOS but you can achieve it doing something like below
NSArray *viewControllers=[self.navigationController viewControllers];
NSMutableArray *newControllers=[[NSMutableArray alloc] init];
for(int i=[viewControllers indexOfObject:self];i<viewControllers.count;i++){
[newControllers addObject:[viewControllers objectAtIndex:i]];
}
[self.navigationController setViewControllers:[[NSArray alloc] initWithArray:newControllers]];
I have tried the method of storing all the view controllers in an array but it didn't work for me . When you try popViewController it will move to the View Controller which is last in the stack.
You can make 2 navigation controllers and switch between them and also switch between the view controllers of a particular Navigation Controller.
For eg.
You can switch between 2 Navigation Controller using the following code:
FirstNavController *fisrtView=[storyboard instantiateViewControllerWithIdentifier:#"firstnavcontroller"];
self.window.rootViewController = firstView;
}else{
SecondNavController *secondView=[storyboard instantiateViewControllerWithIdentifier:#"loginnavcontroller"];
self.window.rootViewController = secondView;
}
If your FirstNavController has 2 ViewControllers then you can switch between them using pushViewController
SecondViewController *sc = [self.storyboard instantiateViewControllerWithIdentifier:#"secondviewcontroller"];
[[self navigationController] pushViewController:sc animated:YES];
and popViewController
[self.navigationController popViewControllerAnimated:YES];
I have setup a UINavigation controller that uses the AppDelegate as the main point of contact.
I have different methods which run such as presentHomeViewController, presentLoginViewController, which push the different view controllers to the Navigation Controller.
App Delegate - didFinishLaunching
welcomeViewController = [[MyWelcomeViewController alloc] initWithNibName:#"MyWelcomeViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
navController.navigationBarHidden = YES;
self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];
self.window.rootViewController = self.revealSideViewController;
Is this the correct process for this?
- (void)presentHomeViewController {
// We start by dismissing the ModalViewConrtoller which is LoginViewController from the welcomeview
[self.welcomeViewController dismissModalViewControllerAnimated:YES];
// Check if the home view controller already exists if not create one
if (!self.homeViewController) {
NSLog(#"presentHomeViewController- Creating the Home View controller");
homeViewController = [[MyHomeViewController alloc] initWithNibName:#"MyHomeViewController" bundle:nil];
}
// Push the homeViewController onto the navController
NSLog(#"presentHomeViewController");
self.navController.navigationBarHidden = NO;
[self.navController setTitle:#"Home"];
[self.navController pushViewController:homeViewController animated:NO];
If I then add the following to a different class :
[self.navigationController pushViewController:accountViewController animated:NO];
No view is pushed to the stack, should I control all the movement within the AppDelegate as I have been doing, or is there betters way to approach this?
EDIT
Thanks for posting your code. So, to address your final question first, I don't recommend controlling your navigation stack from the app delegate. You should be controlling the stack from the view controllers that are the children of the navigation controller.
To that point, remember the hierarchy of view controllers: UINavigationController inherits from UIViewController, and UIViewController has properties defined for all the things you'd see in a navigation layout such navigation items and title. More importantly, it also has properties for its parent view controllers, the view controller that presented it, and its navigation controller. So, considering the hierarchy, your app delegate should only instantiate the navigation controller's root VC and the nav controller itself, and then subsequently set the nav controller's root VC.
From there, you should be pushing and popping other VCs from the VCs themselves. Remember, every VC has a property that's automatically set to point at the navigation controller it's a part of. That's why [self.navigationController pushViewController:] works. For instance, if I have a nav controller whose root VC is a UITableViewController, and tapping on one of the items in the table view pushed a new VC onto the stack, I would push that VC from the table VC and not from the nav controller class or the app delegate.
Sorry if that's confusing. Please let me know if that needs clarification and I'll give it my best. Otherwise, hopefully that gets you on the right track.
I am using a NavigationViewController to navigate between master view and detailed views. Now I want to be able to switch to a sibling detail view without first showing the master view and I have tried doing popViewController and pushViewController in the same method or popViewController in the detailed view and then pushViewController in mater's viewDidLoad after popViewController but it won't work - the view just ends up going back to the master view without switching to the detail. Any idea what to do?
The solution suggested here doesn't work as far as I can tell:
Switching Content Views Issue
I've never tried it, but this should work:
// create instance of new view controller
MyViewController *myViewController = [[MyViewController alloc] init];
// get current stack of viewControllers from navigation controller
NSMutableArray *viewControllers = [[self.navigationController viewControllers] mutableCopy];
// replace top view controller in stack
[viewControllers replaceObjectAtIndex:([viewControllers count] - 1) withObject:myViewController];
// set modified stack of view controllers in navigation controller
[self.navigationController setViewControllers:viewControllers animated:YES];
According to the docs, your app will transition to the new view controller with a push animation, and then when back button is clicked it it will be as if the view controller you pushed from was never there. (If you don't want the animation, use animated:NO)
I'm starting out with iOS Development.
Currently, I've implemented a TabBarController that nests 2 Views, one of which has a TableView within in.
I'm trying to get the table view to Push another view when DidSelectRow is called.
What I am trying to do is similar to the AppStore in the Search Tab.
I.E:
When you find the App you want you tap on the table row - then the search bar fades away and the Navigation bar fades in, revealing more detail.
Right now I'm trying this:
self.nav = [[UINavigationController alloc] initWithRootViewController:rootVC];
nav.delegate = self;
self.detailView = [[detailView alloc] initWithNibName:#"detailView" bundle:nil];
[nav pushViewController:self.detailView animated:YES];
Where rootVC is the viewController in my secondView.
This does nothing. I've called NSLog to make sure that the method is being called, and it is.
Any help is greatly appreciated.
Thanks!
Do you have a navigation controller in the app? One way to achieve the navigation controller with tab bar controller is to add navigation controller for each tab bar item . Then make the root view controller of the navigation controller one of your 2 views controllers.