Pushing a UIViewController from a modal view controller - iphone

I am using a split view controller in an iPad app I am trying to make.
Right now, I have a view being displayed in a modal view controller using:
[self presentModalViewController:viewController animated:YES];
and that works fine, but when the user presses a button, I want the root view controller to push to another view. I am using:
RootViewController *rvc = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
[rcv pushViewController:rvc animated:YES];
but that is not working. What should I do?
--EDIT
Now, I am using
PhotosViewController *pv = [[PhotosViewController alloc] initWithNibName:#"PhotosViewController" bundle:nil];
[self.parentViewController.navigationController pushViewController:pv animated:YES];
NSLog(#"Navigation Controller: %#", self.parentViewController.naviagtionController);
When I do the NSLog call, it returns nil. Why is that?
Once again, I am using a split view controller and am trying to push the RootViewController to a new view.
Thanks

Your code isn't working because you're created a RootViewController instance and then trying to push it onto itself. What you should be doing is pushing the new view controller onto the parent view controller's navigation controller:
[self.parentViewController.navigationController pushViewController:newViewController animated:YES];

I know this is an old question but I believe the proper way "now" to push a viewController onto the main navigation stack from a modal viewController is to create a "didTapShowBlahViewController" delegate on the modal (this is assuming you want the user to be finished with the existing modal view and then push a new view onto the stack). Once you have that delegate, you simply have the view that initially invoked the modal to perform dismissing the modal and pushing the next view controller when the delegate is triggered.
- (void)didTapShowBlahViewController{
[self dismissViewControllerAnimated:YES completion: nil];
[self performSegueWithIdentifier:#"segueToBlahViewController" sender:self];
}
This is based on Apple's View Controller Programming Guide that specifies passing data to child view controllers and using delegates to pass data back to parents.
FYI: This way also ensures that the "back" button will not go back to the modal but instead to the view that invoked the modal, which is how modals are typically used.

Related

Warning: Attempt to present <CustomViewController> on <UINavigationontroller> whose view is not in the window hierarchy

I know this has been asked a million times, but I couldn't find a suitable answer in those many questions that I've examined.
I have a custom view controller, and I'm trying to display the view controller when the user taps a button (so no "infamous viewDidLoad problem" here).
Here is my code that runs when the user taps the button: (I have the NIB for the view controller, and I have a navigation controller)
ICLoginViewController *loginViewController = [[ICLoginViewController alloc] initWithNibName:#"ICLoginViewController" bundle:[NSBundle mainBundle]];
//assuming we have a navigation controller.
UINavigationController *navigationController= (UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController;
[navigationController.topViewController presentViewController:loginViewController animated:YES completion:nil];
I'm getting the Warning: Attempt to present <ICLoginViewController: 0xa08a810> on <UINavigationController: 0xa45de70> whose view is not in the window hierarchy! error when I try to present the view controller. Nothing happens on screen. If I tap multiple times I get the same error, and still nothing happens. I've set a breakpoint and verified that navigationController and navigationController.topViewController are not nil. I' using storyboard (if it helps) but not for the custom view controller that I'm trying to display. (I want to make it an app-independent library in the long run, so I'm not referencing any app-specific modules within) Why am I getting this error?
I've found the solution. The problem was, my modally displayed view controller was not the 'top' view controller in navigation controller. If I change the calling view controller to be pushed instead of being modal, then it becomes the top view controller and my app works well. Apparently, this had nothing to do with my custom view controller, but my navigation stack.
If its in an NSObject create a method inside the NSObject that takes your current viewController as an argument and present it there.
eg:
-(void)presentInViewController:(UIViewController *)controller{
ICLoginViewController *loginViewController = [[ICLoginViewController alloc] initWithNibName:#"ICLoginViewController" bundle:[NSBundle mainBundle]];
[controller presentViewController:loginViewController animated:YES completion:^(BOOL comp){}];
}
This way you can call that view controller wherever you want instead of trying to find your way through the navigation stack from UIApplication.

Loading another UIView directly from the main ViewController

I am in the process of creating an application. In the main ViewController I have created the menu. But I want to have a login screen (UIView) to appear before the menu is visible.
But because the menu loads as soon as I run the application I have decided to create another UIView controller and have that loaded on top of the main ViewController.
Therefore at the end of my main ViewController viewDidLoad I have added the following code to open on top of that view the login view
LoginPageView *loginPageView = [[LoginPageView alloc] initWithNibName:#"LoginPageView" bundle:nil];
loginPageView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:loginPageView animated:YES];
As I know the purpose of that code is to present another view, but unfortunately the login view does not appear. Only the main ViewController load.
Can anyone help me on that? Have you realised what exactly I want?
Thanks a lot
In the viewDidLoad method, the view exists, but there is no guarantee that the view is already part of the view hierarchy of your application. In fact, almost ain't.
What you can try is take that code in the viewWillAppear: or viewDidAppear:.
Make a UINavigationController. Use this as your window's root view controller. Set the UINavigationController to not show the navigation bar.
Set the navigation controller's child view controller to your login view controller.
When the user logs in successfully, create your main view controller and push it, like this:
MainViewController *mainVC = [[MainViewController alloc] initWithWhatever...];
[self.navigationController pushViewController:mainVC animated:YES];
When the user logs out, you can just do this to get back to the login VC:
[self.navigationController popViewControllerAnimated:YES];

iPhone - change navigation controller's view, using a button in a subview

I have a navigation controller with a rootview.
The rootview contains buttons, which push new views onto the navigation controller correctly.
However, on this rootview, I also have subview (it's a scrolling preview like the appStore images, view made of 3 UIview items). On these UIViews, there is a button which I'd like to change the rootview navigation controller, like the other buttons.
At the moment, it builds and runs, but the new view is not pushed. Any ideas?
Click method on on the ScrollItem button:
MyViewController *newView = [[MyViewController alloc] initWithNibName:#"ManageMyPain" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:newView animated:YES];
... i guess it is because, self doesn't have a navigation controller, but the rootview does.
Thanks!!
The property "navigationController" is only being set in a view controller if he's pushed to the navigation controllers stack. your second view is a sub view of a push viewcontroller which means this property is NULL and will not do anything if you try pushing things to it.
Yes, it is because self.navigationController will be nil if you didn't push that controller on navigations stack or if you didn't set it manually.
So you just need to have reference to rootViewController.navigationController and then [navigationController pushViewController:newView animated:YES]; will work perfectly.

how to flip from one view to another view in iphone sdk

I wan't to flip from one view controller to another for that i used following coding on button click
-(void)ClicOnLogout {
LogOutViewController *logOut=[[LogOutViewController alloc]initwithnName:str];
logOut.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:logOut animated:YES];
}
but when i m in logout view controller there is one button but it won't work so can any one give me the proper solution for it.
Thanx...
You should read that Apple documentation article on Modal View Controllers which explains everything you are asking there. Basically what you need to do on your logout view is to call :
[self dismissModalViewControllerAnimated:YES];
By calling this, the back (left-to-right) flip animation will be done automatically :
UIModalTransitionStyleFlipHorizontal
When the view controller is presented, the current view initiates a horizontal 3D flip from right-to-left, resulting in the revealing of the new view as if it were on the back of the previous view. On dismissal, the flip occurs from left-to-right, returning to the original view.
You can call the popViewControllerAnimated method:
[self.navigationController popViewControllerAnimated:YES];
or you can assign it to push it onto the navigation controllers stack:
[self.navigationController pushViewController: viewController animated:YES];

iPhone - how do I add a navigation controller to a view?

I currently have an application that does the the following:
S: Loads a view as a login screen to start with.
a: If login is successful I add a terms and conditions screen as a subview
b: If not successful I add a sign up form as a subview
F: Then I load the main part of my app on success of either of the a or b which is the part of the app where there is a navigation controller and a tab bar controller. This is set up in MainWindow.xib
S, a and b also have Nav bars but no navigation controllers as I didn't think I would need navigation control on the login screens.
However it turns out I do, I want to be able to have back navigation from both a and b to the initial login screen.
I have tried several ways of doing this including trying the following answers:
How to add navigation controller in View Based Application in iPhone?
How do you properly set up a secondary view to support a navigation Controller on the iPhone?
how to add navigation controller programatically?
But none of them work for me, they display the new Navigation controller over the login screen and dont load the a or b screens.
I'm guessing this is because I am adding them as subviews to my loginView and this is not the correct way to do this? My code is as follows:
if(self.tcSubViewController == nil){
TCSubViewController *_tcSubViewController = [[TCSubViewController alloc] initWithNibName:#"T&CView" bundle:[NSBundle mainBundle]];
self.tcSubViewController = _tcSubViewController;
[_tcSubViewController release];
}
[self.view addSubview:[tcSubViewController view]];
I'm guessing there's a fundamental flaw in the way my Login flows? I should be able to completely remove the LoginView and then display the Terms and conditions view without having to add it as subview, shouldn't I?
You need to dismiss the navigation controller to go back to.
To dismiss modal view:
1.Easy way: In your modal view in some method that you call to dismiss just add:
[self.navigationController dismissModalViewControllerAnimated:YES];
2.More complex way: Implement and delegate protocol on your modal view and make the view controller that presents the modal view the delegate of it. And in the delegate method dismiss the modal view. I do this way when I need to send data from modal view to the controller that present it.
Reference to this post
Navigation controller philosophy is that you add only navigationController.view as UIWindow subview and it wil manage the rest by itself. You only need to push/pop viewControllers and their corresponding views will be added/removed from screen automatically.
sample code from my current application:
HomeController *homeController = [[[HomeController alloc] init] autorelease];
self.controller = [[[UINavigationController alloc] initWithRootViewController:homeController] autorelease];
self.controller.navigationBarHidden = YES;
[self.window addSubview:self.controller.view];
[self.window makeKeyAndVisible];
and then to push next view you just add next controller:
[self.navigationController pushViewController:newController animated:YES];