I just changed my app and Im quite confused. It started with the root view that then pushed a second view, there is a button on that view that pushes another view...
So I decided to instead present that second view controller but now the other view cant be pushed from the second.
Code From Root View:
//This works
[[self navigationController] presentViewController:secondViewController
animated:YES completion:nil];
Code From Second View:
//This Does not work
[[self navigationController] pushViewController:locactionView animated:YES];
Edit: Sorry for the lack of detail. No exception is thrown it simply doesn't push the "Location View." Before I presented the view I pushed it and everything worked fine. Also when the view was originally pushed the navigation bar was visible, now that the View Controller is being presented I can't push a view or see the Nav Bar. I hope this helps. I don't know what code I could add because I only changed a single line before the problem occurred.
In your AppDelegate you could initialize your NavigationController with the rootViewController first, and then you could push the viewControllers on the stack, that could solve your problem
YourNavigationController *yourNavigationController = [[YourNavigationController alloc] initWithRootViewController:self.firstViewController];
If you have your hierarchy set up like this:
self.rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController"
bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.rootViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
You should not have any issues with this stuff. Your issue might be that you are trying to push onto the navigation controller from a view controller you presented modally which you cant do
Related
Here is the code I am calling to pop a navigation controller over my entire tab bar app:
LoginViewController *logController = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
EditNavController *navController = [[EditNavController alloc] initWithRootViewController:logController];
[self.navigationController presentModalViewController:navController animated:NO];
and I am getting the following warning in my log:
Warning: Attempt to present <EditNavController: 0xa95b980> on <MyTabController: 0x1152fd60> whose view is not in the window hierarchy!
The code works, but I want to do it the correct way so this warning doesn't appear.
How do I fix this?
if MyTabController is a tabbarcontroller, you should use
[self presentViewController:navController animated:YES completion:^{}];
remember that presentModalViewController:animated: is deprecated since iOS6. I think the problem is you are trying to present the viewController in Navigation Controller of the tabbar, wich is not in the view hierarchy (because it's not shown). Instead, you should present the modal view controller in the Tab Bar controller (wich IS in the view hierarchy).
I hope it helps!
I am trying to push a new root controller to a navigation stack, but using a side reveal menu.
My app delegate has the following:
welcomeViewController = [[MyWelcomeViewController alloc] initWithNibName:#"MyWelcomeViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
navController.navigationBarHidden = YES;
// Then we setup the reveal side view controller with the root view controller as the navigation controller
self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];
// Then we make the window root view controller the reveal side view controller
self.window.rootViewController = self.revealSideViewController;
Once the welcome view controller is displayed, the user logs in. Once logged in the following process runs again from the App Delegate.
self.navController.navigationBarHidden = NO;
[self.navController setTitle:#"Home"];
[self.navController pushViewController:homeViewController animated:NO];
I then have a side view controller setup which is a table view with custom cells setup.
When a row is selected I need to push a new root controller onto the navigation controller. I try this by using the following in the table view for the cell selected.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[self.navigationController setViewControllers:[NSArray arrayWithObject:accountViewController] animated:NO];
Unfortunately this does not do anything. If I add the code to the App Delegate and then call the method from the table view controller then it works, however not from the .m file for the table view itself. Adding a log I can see the above is run, just does not do anything.
I am unsure if I need to do anything different on the above. For example, completely pop the views currently shown, then create the navigation controller and PPRevealSideViewController all over again. If I am supposed to, I am unsure how to pop all the current views to then push the new to the window, not from the AppDelegate.
The reason I do not want this in the App Delegate is because it is the incorrect way to approach this, and I would then need a separate method for each new root controller I would like to push from the menu, so the App Delegate would become very large.
Check UINavigationController.h:
#interface UIViewController (UINavigationControllerItem)
#property(nonatomic,readonly,retain) UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it.
It means when you do myViewController.navigationController you will either get nil if myViewController is not pushed to any navController or the navController reference myViewController is pushed into.
As I understand your tableViewController is not pushed into the navController stack, that means you can't get the navController with tableViewController.navigationController. Instead you'll need to use anyViewControllerInTheStack.navigationController or if the navController is the rootViewController of your keyWindow, by
((UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController)
Add something like this to your AppDelegate.h:
#define XAppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])
Now you can access any iVar of AppDelegate from any .m file in your project.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[XAppDelegate.navController pushViewController:accountViewController animated:NO];
Make sure you add the correct imports.
One more thing: It's good to pop the login window from your navcontroller once you are done Logging in.
Hope this helps.
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'm trying to get working a simple operation. At least it seems simple. Ok, what I'd like to do is to push a view (with push view controller) from a view that has been pushed with modal view controller.
View1 --(push using modal view controller)-->View2--(push using push view controller)--View3.
Rigth now, i'm doing tests so i'm using a button to start the action. Here's the code I use to push from View2 to view 3:
//view2.h
UIToolbar *bar;
UIBarButtonItem *button;
UIToolbar *toolbar;
}
- (IBAction)demissModal:(id)sender;
- (IBAction)goView3:(id)sender;
#end
//view2.m
- (IBAction)goView3:(id)sender{
View3 *view_3 = [[View3 alloc] initWithNibName:#"View3" bundle:nil];
[self.navigationController pushViewController:view_3 animated:YES];
}
This is the same code I use to push View1 to View2, and it works. But when pushing View2 to View3, it's not working. Any idea of why happens that? Thanks!
View Controllers aren't actually 'modal' or 'push' view controllers. Modal or Push describe a transition between view controllers (called segues if you're using storyboards).
What I think you're asking is how to modally present a view controller, and then push another controller. The trick is when you modally present view controller #1, to actually present a navigation controller with its root view controller set as view controller #1.
MyViewController *myViewController = [MyViewController alloc] init];
UINavigationController *navController = [UINavigationController alloc] initWithRootViewController:myViewController];
// Presuming a view controller is asking for the modal transition in the first place.
[self presentViewController:navController animated:YES completion:nil];
// Now in myViewController, call [self.navigationController pushViewController:secondViewController animated:YES];
This is what it looks like using storyboards:
First of all, I'm not sure where that gegant_se is coming from.
Second of all, if you're pushing view2 from view1 the same way you're pushing view3 from view2, you're not using a modal.
Whenever you use a navigation controller to push a view controller, that view controller that was just pushed has a reference to the navigation controller, through the navigationController property. Try this:
[self.navigationController pushViewController:view_3 animated:YES];
Try this:
[self.navigationController pushViewController:view_3 animated:YES];
try this code AlarmList is view name .
AlarmListScreen *loscr=[[AlarmListScreen alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:loscr animated:YES];
[loscr release];
I have a UIViewcontroller that I want to push onto a UINavigationController, which in turn would push onto a modal view using presentModalViewController:animated.
Here's my code:
TargetViewController *targetViewController = [[[TargetViewController alloc] init] autorelease];
UINavigationController *targetNavController = [[[UINavigationController alloc] initWithRootViewController:targetViewController] autorelease];
[self presentModalViewController:targetNavController animated:YES];
When code is run, the modal view loads as expected, but after dismissModalViewControllerAnimated: is called, the modal view slides down and the app crashes.
I get the following error in gdb:
-[CALayer retain]: message sent to deallocated instance
First part of question: is there anything inherently wrong with the above code?
Second part: if there is nothing wrong with above code, where should I look next to debug?
Additional info:
When I don't release or autorelease the navController, it works fine. But Instruments will show abandoned memory, which I can only assume is the navController not being released. Maybe the modal view controller
P.S. I know that the crash is related to the memory management of the above ViewController, navController and modal view, because my code was working prior to messing with this code.
You generally don't push a navController as a view as the navigation controller works as the root controller. The views are pushed from the navController. Once you have a view pushed, you could then present the next view modally.
What happens if you don't use autorelease?
I.E.:
TargetViewController *targetViewController = [[TargetViewController alloc] init];
UINavigationController *targetNavController = [[UINavigationController alloc] initWithRootViewController:targetViewController];
[targetViewController release];
[self presentModalViewController:targetNavController animated:YES];
[targetNavController release];
Fixed the issue. I was releasing the VC, causing the crash. Thanks for the input.