How to swap the window.rootViewController without using an UINavigationController? - ios

In the AppDelegate I set an UIViewController, let's call it VC, as the rootViewControlloer for my app:
-(BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
{
self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
UIViewController *VC = [UIViewController alloc] init];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
Once VC is on the screen, it asks the user a couple of questions to better configure the app before the real use.
As soon as I know what the user wants I need to swap VC with an UITabBarController, let's call it TBC, with three UINavigationController anchored to it.
How can I push TBC from VC whithout putting VC inside an UINavigationController and then use it to push TBC?
I am already able to accomplish the swap using the UINavigationController.I want a direct transiction from VC to TBC, a swap of the self.window.rootViewController whitout the need to use the extra UINavigationController.

Instead of navigating through the view controllers just create a method in app delegate which would change the root controller such as
-(void)showTBC
{
self.TBC=[[UITabbarcontroller alloc]init];
[self.window setRootViewController:self.TBC];
[self.window makeKeyAndVisible];
}
and den in your VC right after the user selects the answer make an instance of app delegate
in VC such as
AppDelegate *ap=(AppDelegate *)[[UIApplication sharedApplication]delegate];
and call
[ap showTBC];
…it worked for me..give it a try...

Related

iOS MMDrawerController objective-c login view controller

I am begin to study iOS and I try to do left navigation with MMDrawerController
my AppDelegate didFinishLaunchingWithOptions code is:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *leftView = [mainStoryboard instantiateViewControllerWithIdentifier:#"LeftViewController"];
UINavigationController *leftNav = [[UINavigationController alloc]initWithRootViewController:leftView];
UIViewController *centerView = [mainStoryboard instantiateViewControllerWithIdentifier:#"CenterViewController"];
UINavigationController *centerNav = [[UINavigationController alloc]initWithRootViewController:centerView ];
self.drawerController = [[MMDrawerController alloc] initWithCenterViewController:centerNav leftDrawerViewController:leftNav];
self.drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModePanningCenterView;
self.drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModePanningCenterView;
self.window.rootViewController = self.drawerController;
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
So it's work fine, but I have LoginViewController on my app, and if user has no saved token on NSUserDefaults, I must show LogionViewController.
Of course side menu must be hidden on LoginViewController.
I Tried to switch to LoginViewController inside my CenterViewController:
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController * vc = [[LoginViewController alloc] init];
AppDelegate *app = [[UIApplication sharedApplication] delegate];
[app.drawerController setCenterViewController:vc withCloseAnimation:YES completion:nil];
}
But I have black screen only.
What I do wrong?
Thanks
What you're doing is a bit weird because you are setting the new centerViewController (of type LoginViewController) within the current one (of type CenterViewController), and once that is done the latter one will be deallocated because there are no more references to it. This might somehow be causing the black screen.
One solution would be to have the LoginViewController outside the MMDrawerController, and always present it at the beginning. If there is no token, then quickly (without animation) present the MMDrawerController and the LoginViewController won't even be seen. This way also allows you to easily dismiss back to the login screen if the user logs out.
Another option is to just present your LoginViewController from the CenterViewController modally (or however you like really) using presentViewController:animated:completion:, and then just dismiss it when they log in.

Presenting NavigationalViewController in TabbarController

I'm developing an iOS application and structure is tab bar based. My root view controller is TabBarController but I need to present a navigational view controller in the beginning of the application if app is launched for the first time. I implemented a FlowViewController to control flow of the application. In FlowViewController, I create TabBarController and assign it as a rootviewcontroller.
How can I present a navigational view controller in the beginning of application and then present TabBarController.
FlowViewController
TabBarViewController *rootVC = [[TabBarViewController alloc] init];
rootVC.delegate = self;
rootVC.tabBar.translucent = NO;
self.rootViewController = rootVC;
In AppDelegate, didFinishLaunchingWithOptions
self.flowController = [[FlowController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[ [UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = self.flowController.rootViewController;
[self.window makeKeyAndVisible];
If a setup screen is needed in an app normally I will use NSUserDefaults to check whether the app has been launched before in viewDidLoad(). If not then I will present the setup viewController. Once the user has completed the setup process add the something to NSUserDefaults so when the app is launched it knows the user has been through the process already.
In my application, I have set UINavigationController as root view controller. Then I have added the TabBarController as child of UINavigationController.
Design the view controllers in StoryBoard, as you want. Set Storyboard id for UITabBarController and call tab bar controller using that storyboard identifier.
-(IBAction)LoginAction:(id)sender{
UITabBarController *loadTabBar = [self.storyboard instantiateViewControllerWithIdentifier:#"TabBarViewControllerID"];
[self.navigationController pushViewController:loadTabBar animated:YES];
}

iOS initial log in view before navigational Controller

I have been playing around with this for a couple of days and I cannot figure this out.
-> Basically I want to implement a simple login view that has a button when clicked, goes to go to the navigation controller ( in my case is "viewController" with buttons that link to mini math games which are other views).
-> Login screen should be displayed first, than navigation controller's root view when a button is clicked on the login screen
-> I have tried to declare the navigation controller when I click the button of the login screen but that seems to not work
-> Is it safe to say that a navigation controller can only be initialized in the apple delegate?
Currently I have this in my apple delegate declaring and setting my navigational controller:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navigationViewController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; // self.viewController is the main screen
self.window.rootViewController = navigationViewController; // set root to navigationViewController
[self.window makeKeyAndVisible];
return YES;
}
Any ideas will be appreciated. Thank you for your time !
Your code in the app delegate looks ok. NavigationController does not need to be declared in the AppDelegate. In your case, it is definitely ok to declare it upon login button pressed.
Try this at the login event:
UIViewController *nextVC = [[UIViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:nextVC];
[self presentViewController:navController animated:YES completion:^{
}];
What I would do would be set the loginViewController as the rootViewController of the navigation. And after check if login was done successfully, you could implement [self performSegueWithIdentifier:#"identifier"] setting the game viewController as destination. (Using Storyboard would make your life much easier). Well, that's my opinion :)

Can [self.window makeKeyAndVisible]; be called before setting rootviewcontroller

My requirement is that UITabBarController is the rootviewcontroller and on very first time of app launch I want to show login procedure which is inside UINavCon, and I am displaying it through presentViewController.
I dont want the UITabBarController visible for first time and dont want to how login UINavCon popping as modal.
I want to make user experience that if app starts for first time login UINavCon should be visible. So here is my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];//is it correct to call it here?
LoginVC *loginObj = [[LoginVC alloc]init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:cellPhoneNumber];
self.tabBarController = [[UITabBarController alloc]init];
self.window.rootViewController = self.tabBarController;
[self.tabBarController presentViewController:self.navigationController animated:NO completion:^{}];
return YES;
}
I am calling [self.window makeKeyAndVisible]; on second line right after uiwindow alloc init. Is it correct do this or I can experience problems like viewcontroller not receiving events or orientations notifications?
you can call it whenever you want. Calling it affects the window's z-index and screen property.
it doesnt depend on any specific content being set.
You haven't mentioned that whether you got the code working or not by using your implementation. Anyways I have done similar kind of implementation recently where we need to present login controller and then tabBarController after logging in, so just sharing my implementation.
Create your login controller and present it in didFinishLaunching method.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
LoginController *loginCObj= [[[MainScreenController alloc]init]autorelease];
UINavigationController *navigationControllerObj = [[[UINavigationController alloc]initWithRootViewController:loginObj]autorelease];
self.window.rootViewController = navigationControllerObj;
[self.window makeKeyAndVisible];
After that on succesful login in your login view controller, call an appDelegate public method
In login controller
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDel applicationLoggedInSuccesfully];
In your appDelegate file, add a method like this:
-(void)applicationLoggedInSuccesfully{
UINavigationController *nv1 = [[[UINavigationController alloc] initWithNibName:nil bundle:nil]autorelease];
TabController1 *v1 = [[[TabController1 alloc] initWithNibName:nil bundle:nil]autorelease];
[nv1 pushViewController:v1 animated:NO];
UITabBarController *tabController = [[[UITabBarController alloc] init]autorelease];
tabController.viewControllers = #[nv1];
tabController.delegate = self;
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
}
Hope it will help you.

Tabbed application won't show Login view

I have a tab bar application in Xcode 4.3 and I'm trying to insert a login screen before the tabbar is shown. The app works OK if presentModalViewController has animated:YESbut if it is without animation the view is not showing.
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
LogInViewController *logViewController = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.window addSubview:_tabBarController.view];
[self.tabBarController presentModalViewController:logViewController animated:YES];
//This wont work
//[self.tabBarController presentModalViewController:logViewController animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
-(void)loginDone{
NSLog(#"back to the app delegate");
[self.tabBarController dismissModalViewControllerAnimated:YES];
}
Is this the right way to do it?
Why wont the code work with animated:NO ?
I also get this on output Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x689d350>.
First of all, move [self.window makeKeyAndVisible]; before your view controller setup.
Additionally, you should be presenting the modal view controller within the viewWillAppear: method of the view controller that will be visible first, to make sure your apps view hierarchy has been fully initialized before presenting your login screen.
Don't do this:
[self.window addSubview:_tabBarController.view];
Do this:
self.window.rootViewController = _tabBarController;
This will put the tabBarController on the screen. But that's not exactly what you want... My advise is:
1) Start by putting the logViewController has the rootViewController as I showed you above.
2) Once you got what you want (login is successful) just tell the AppDelegate to switch the rootViewController. This can be done in with delegation or notifications.
Also, as Toastor indirectly pointed out, you should start the presentViewController from the UIViewController who actually initiates it (and not from the AppDelegate).

Resources