How to Set SwRevealview controller as Root view controller - ios

I am using SwReveal view controller.It is initially set as root view controller. I am using a Login screen when app logged in I remember the user name and next time when the app is opened i set a main screen as Root view controller. But here where my problem starts. When i set main screen as Root view controller SWREVEAL view controller is no longer my root view controller. How to set SWRevealController back to Root view controller in Main screen View did load method.
Here is how i set main screen as Root view controller
TimeTableViewController * time = (TimeTableViewController *)[sb instantiateViewControllerWithIdentifier:#"Time"];
navigation = [[UINavigationController alloc]initWithRootViewController:time];
self.window.rootViewController = navigation;
// [self.window setRootViewController:navigation];
[self.window addSubview:navigation.view];
[self.window makeKeyAndVisible];
Here is how my Reveal view controller is set.. its in Main Screen View did load method. But becoz of i changed the root view controller from "SWREVALVIEWCONTROLLER" to "Main screen" view controller the below code doesnt work and doest open up the reveal. Please help
LearningSearchController *slideView = [[LearningSearchController alloc]init];
slideView.delegate = self;
[(LearningSearchController *)self.revealViewController.rightViewController setDelegate:self];

I think your problem is Login Screen. Keep SwRevealViewController as rootview controller and for login check in frontview screen. If user is not logged in then present LoginViewController. For example MainScreen is a frontview for SwRevealViewController then in viewdidLoad check user is already logged in or not.

Related

iOS Warning: attempt to present ViewController whose view is not in the window hierarchy

I know there are lot of discussions around this warning and we should be presenting the view controller only after presenting view controller is completely presented and added in view hierarchy. All these rules are followed and I am still getting this warning when presenting second modal view controller.
This the complete sequence of actions happening here:
On app launch, initialized and added base view controller to window.
From base view controller, on tap on a button, modally presented first view controller.
From first view controller, on tap on a button, modally presented second view controller. Once dismissed, I need to show first view controller so I am not dismissing first VC and then presenting second VC from base VC.
Warning in console:
2015-03-11 13:15:43.467 MyApp[597:84839] Warning: Attempt to present <MyCustomNavigationViewController: 0x15d6a8920> on <MyFirstModalViewController: 0x15d67cc60> whose view is not in the window hierarchy!
Thoughts?
Below is my code [Not showing button handlers; took code from within the calling methods]:
// Present base view controller
self.window.backgroundColor = [UIColor whiteColor];
self.primaryViewController = [[MyParentViewController alloc] init];
self.navigationController = [[MyCustomNavigationViewController alloc] initWithRootViewController:self.primaryViewController];
[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
// Present first view controller modally from base view controller
MyFirstModalViewController *firstModal = [[MyFirstModalViewController alloc] init];
MyCustomNavigationViewController *aNavigationController = [[MyCustomNavigationViewController alloc] initWithRootViewController:firstModal];
[aNavigationController.navigationBar setBarStyle:UIBarStyleBlack];
[self presentViewController:aNavigationController animated:YES completion:nil];
// Present second view controller modally from first view controller: On user tap on a button
MySecondModalViewController *secondModal = [[MySecondModalViewController alloc] init];
MyCustomNavigationViewController *aNavigationController = [[MyCustomNavigationViewController alloc] initWithRootViewController:secondModal];
[aNavigationController.navigationBar setBarStyle:UIBarStyleBlack];
[self presentViewController:aNavigationController animated:YES completion:nil];
If the code you're displaying in your question is in the exact order that it runs on app launch, it's because it's trying to animate the second Modal viewcontroller (the third actual view controller being presented) when the first modal has not finished animating.
On these two lines - [self presentViewController:aNavigationController animated:YES completion:nil]; set animated:NO. This will make those views appear instantaneously, and may remove the error you're getting.
If you need the animation, and you need the views to all open instantaneously like you've written, then you might want to implement a delay before the third viewcontroller (second modal) is called.
You say you're calling these views from buttons? The code indicates otherwise.

Split view controller at non root position IOS

Hi I am new to IOS development. I am developing small application I want to use split view. But that split view is not my root view. My application start with login which is not split view. After login I want to start my main view which is split view controller. So here is my problem if I set main view as root view i.e. start point for my application it works fine. But If I set my login controller as root controller then it gives exception. In my AppDelegate I am setting following things:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
SidePannelViewController *controller = (SidePannelViewController *)masterNavigationController.topViewController;
controller.splitViewController = splitViewController;
splitViewController.delegate = (id)controller;
once I set my main view as root controller it works fine. How to solve this problem? Need Help. I want to keep my login screen as normal login view controller and after login start split view controller. Thank you.
You can present the LoginScreen as modal over the top of the split view controller, else you can initially set LoginScreen as rootViewController and then replace with SplitViewController as rootController.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
Once user logged in successfully dismiss the loginscreen.
Hope this helps.
You can set the LoginViewController as the root view controller when the user is not logged in and changed the root to split view if the user is logged in. Just put the check in didFinishLaunchingWithOptions method to check if the user is logged in or not and set your root accordingly.

iOS push current view controller onto another view controller hierarchy

I have a view controller (which is the root view of the main UINavigationController for my app) that is presenting another view controller hierarchy modally, by presenting a UINavigationController. After the user interacts with the root view controller in the modal NavController, a detail VC is pushed onto the modal NavController's stack. After some interaction with this detail VC, I'd like to push this detail VC back onto the original hierarchy, and dismiss the modal NavController/it's root view controller, all without the user seeing the change in this hierarchy. Right now I have something like this:
In MyViewController1 (root of the main NavController hierarchy):
UINavigationController *newModalNavController = [[UINavigationController alloc]
initWithRootViewController:someRootViewController];
[self presentViewController:newModalNavController animated:YES completion:nil];
Then in the someRootViewController above, after some interaction (e.g. a button click), I push the detail view controller onto the modal hierarchy:
[self.navigationController pushViewController:detailVC animated:YES];
Finally, in the detailVC, after some more interaction:
UINavigationController *mainNavController = /* Get main nav controller here (i.e. non-modal one) */
// Dismisses the modal view hierarchy (detailVC gets -(void)viewDidDisappear)
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
// Repush the detailVC back onto the main hierarchy (detailVC gets -(void)viewDidAppear)
[mainNavController pushViewController:self animated:NO];
// Keyboard was on screen before interaction; make it stay on screen after pushing
// detailVC onto main nav hierarchy
[self.textView becomeFirstResponder];
This all works (clicking back on the detailVC's navigationItem after pushing it onto the mainNavController's hierarchy goes back to the original rootViewController, MyViewController1), except when the keyboard is on screen in the detail view controller as it is being switched, it gets hidden and then animates back up, instead of just staying on screen (because the view is disappearing for a second as the presentingViewController dismisses the modal nav controller, whose hierarchy the detailVC is a part of, and then reappears as it gets pushed onto the mainNavController's stack, and the textView grabs first responder again).
Is there a better way to change which navigation hierarchy the detail view controller is a part of, possibly one that doesn't involve the view disappearing, and thus the keyboard being hidden and immediately reshown?

Setting up a UINavigation controller and various view loads

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.

UINavigationController not pushing view controller

I have created an application that has a Login.
It starts with a Welcome View Controller, checks if the user is logged in if not, opens a Login View Controller. If the user is logged in, or once they have it pushes the user to the Home View Controller like this.
App Delegate (did finish launching)
self.welcomeViewController = [[APPWelcomeViewController alloc] init];
self.homeViewController = [[APPHomeViewController alloc] initWithNibName:#"APPHomeViewController" bundle:nil];
self.navController = [[UINavigationController alloc] initWithRootViewController:self.welcomeViewController];
self.navController.navigationBarHidden = YES;
self.window.rootViewController = self.navController;
Once the user is logged in it pushes the home view.
// Push the homeViewController onto the navController
[self.navController pushViewController:self.homeViewController animated:YES];
This all works fine up to this point. I then use a modal view controller for the Setting, which includes a button to Logout. The logout of the user runs this:
// Log the user out
[User logOut];
// Then we need to remove the Settings Modal View Conrtoller
[self.presentingViewController dismissModalViewControllerAnimated:YES];
// Then we need to take user back to welcomeViewController
[self.navigationController pushViewController:welcomeViewController animated:YES];
It dismisses the Settings View controller as expected, but the navigation controller remains on the Home view. There is no error, does anyone know why this is not working correctly?
Resolved by re-arranging code. Searching for current user on the appdelegate instead then either loading the nav controller with the root controller of home view or running a method to load the welcome view controller.
The welcome view controller then checks for user as well, if not current user it presents the modal login view controller
you dont need to push navigation controller, once you init your window with the navigation controller that contain the welcome view controller.
if you want to add more view inside this stack (inside welcome view controller) you call method self.navigation controller pushviewcontroller ... if you want to remove from stack, call popviewcontroller..you ll go to your main view stack (root).
Try this:
// Take me back to the root navigation view controller (APPWelcomeViewController)
[self.navigationController popToRootViewControllerAnimated:YES];

Resources