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.
Related
Here is the scenario:
The first scene in my storyboard is a login view. It's a UIViewController. When the user is logged in, it shows the home view which is embedded in a navigation controller. I'm adding a log out functionality which should take me back to the first scene in the storyboard which is the login view. How do I do that?
Here is an image of the storyboard showing the login view -> navigation controller -> home view
This is my implementation so far. In the log out action, I clear the session, and pop to root view controller. It does not work because I am still stuck on the home view since it is the root view controller of the navigation controller. However, If I restart the app, the user is logged out and I'm left with the login view.
Code:
[self.navigationController popToRootViewControllerAnimated:NO];
// Set at beginning of storyboard
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
app.loginViewController = [mystoryboard instantiateViewControllerWithIdentifier:#"loginViewController"];
Use unwind segues for that.
In your LoginViewController, declare a method with this signature
- (IBAction)unwindToLoginViewController:(UIStoryboardSegue*)segue
Go to your HomeViewController and control drag from your logout button to the Exit button at the top of your view controller window (see screenshot below), then select the unwindToLoginViewController segue. That's it!
U can pop by using navigationController.viewControllers.Get all View Controllers among navigationController,identify it and then pop.If u have pushed the segue from LoginView to HomeView
if([self.navigationController.viewControllers[0] isKindOfClass:[LoginViewController class]])
{
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:YES];
}
Hope it helps you...
Try this answer. First you create a navigation controller. make it "is initial View Controller". After that connect login Viewcontroller as a root view controller And connect home controller with facebook button Action.
Navigation Controller -> Login Controller -> Home Controller
Your Storyboard is look like this
After that when you logout from HomeViewController then Just add this method:
-(IBAction)logOut_Action:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
Its working Fine. Please implement like this and let me know if you face any problem. :)
Try this:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
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.
I have an app with a LoginViewController as the initial view.
Note: So in appDelegate.m, self.window.rootViewController is NOT the TabBarController.
After Auth, I present the main part of the app, which has a tabbarController (identifier:tabBar) with two tabs and one tab has a navigation controller. I am using Core Data, so I need to pass MOC.
If I use,
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UITabBarController *obj=[storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
[obj setSelectedIndex:0];// Which tab to show first
[self presentModalViewController:obj animated:YES];
It works good visually. Now I need to pass the MOC. Read about PrepareToSegue method,created a segue (modal, Not shown in pic) from loginVC to my TargetViewController (TabBar>NavigationController1>View1), named the segue "LoginSegue" and used the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
View1 *devicelist = (View1 *)[[navController viewControllers] lastObject];
devicelist.managedObjectContext = managedObjectContext;
}
The TabBar does not show. How do i set the tabbar controller in this case?
I have been trying to get a grasp on getting a reference for the Modal Tabbar, but still not clear. Can some one explain in layman terms how to handle a situation like this?
I think it would be better to use a design that doesn't use a modal transition to the tab bar controller. Modal presentations are generally supposed to be for interruptions to the normal flow of the app, not for getting your main controller on the screen. There are two alternatives, that I think are better. You can leave the login controller as the initial root view controller of the window, but then switch it out for the tab bar controller (which will be the new root view controller of the window, and the login controller will be deallocated). This usually works ok, but I think in this case where you want to pass the MOC from the app delegate (I presume) to a controller in the tab bar controller, I think a second way would be better.
The second way to do this, and the way I usually do login controllers, is to have the tab bar controller be the root view controller of the window, and then present the login controller modally from the viewDidAppear method of the initial view (which would be the one you're calling View1). If you do this presentation with animation set to NO, the login controller will be the first thing the user sees:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
static int first = 1;
if (first) {
LoginViewController *login = [self.storyboard instantiateViewControllerWithIdentifier:#"Login"];
[self presentViewController:login animated:NO completion:nil];
first = 0;
}
}
The if statement is in there so the presentation doesn't happen again when you come back from the login controller (you could do something more sophisticated like having a delegate call back to View1 from the login controller indicating that the login was successful if you want, but this works).
If the login succeeds, you just dismiss the login controller, and you'll be there in your first view (if it fails, you just never dismiss it, and maybe put up a message saying the login failed).
If you go this route, then you can pass the MOC in the app delegate like this:
UINavigationController *nav = [(UITabBarController *)self.window.rootViewController viewControllers][0];
View1 *devicelist = (View1 *)nav.viewControllers.lastObject;
devicelist.managedObjectContext = managedObjectContext;
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 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];