Presenting a view for the first time in appDelegate - ios

The goal:
When my app starts up - I need it to display a view before it gets to the "Home" screen. Its a tab bar application and this view is not part of the tabbar.
I am using Storyboards and Xcode 5 - iOS7 only app.
The problem:
I have code that will check if the app is first launch or not. Based on that, I then want to present a one time only view to the user.
What I have tried:
The following code is in the appDelegate of the application as this is where it all starts. I call the following bit of code in there:
-(void)showCountrySettings
{
if (self.termsHaveBeenAccepted){
BBCounterySettingsViewController *countrySettings = [[BBCounterySettingsViewController alloc]initWithNibName:#"View" bundle:nil];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"IDENTIFIER"];
[self.navigationController pushViewController:vc animated:YES];
}
I get compile errors as [self.navigationController..] doesn't exist. Nor does [self.tabbarcontroller...];
This is obvious as I don't have properties setup for these - but how do I go about resolving this and connecting the tab bar to the storyboard?
What am I missing?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if(!isAgreementAccepted)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"IDD"];
self.window.rootViewController=vc;
}
return YES;
}
If agreement is not accepted set the T&C viewController as rootViewController when user click the accept button then set the TabBarviewController as root.
u can access the widow object through application delegate any where
[[[UIApplication sharedApplication]delegate] window].rootViewController=tabViewController.

Change the rootviewcontroller of window programaticaly
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *aStoryBoard=[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
UITabBarController *aTabCtrl=[aStoryBoard instantiateViewControllerWithIdentifier:#"Tab"];
FirstVC *aFirstCtrl=[aStoryBoard instantiateViewControllerWithIdentifier:#"First"];
if(self.termsHaveBeenAccepted)
self.window.rootViewController=aFirstCtrl;
else
self.window.rootViewController=aTabCtrl;
return YES;
}
This will definitely work I have tested.

If Tabbarcontroller is your root viewcontroller, then using below code will resolve the issue in your appdelegate.
-(void)showCountrySettings
{
if (self.termsHaveBeenAccepted){
BBCounterySettingsViewController *countrySettings = [[BBCounterySettingsViewController alloc]initWithNibName:#"View" bundle:nil];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"IDENTIFIER"];
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
[tabBarController presentModalviewcontroller:vc animated:YES completionblock:nil];
}

add your viewcontroller superview of tabbarcontroller as first time else call tabbarcontroller alone

Related

Skip Login View Controller in the NavigationController

I have a tab bar which contains five tabs. My application does not required user to be logged in. Only some features will be allowed if a user signups or logins.
If a user registered/logged in already, I implemented the following logic in the UserViewController which is connected to the NavigationController. However, in the following logic, user still could able to see that ViewController in one-two seconds.
-(void) viewWillAppear: (BOOL) animated
{
if(isRegistered)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UserProfileViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"UserProfileVewController"];
[self.navigationController pushViewController:vc animated:YES];
}
}
I wonder if a user registered already, how could I skip UserViewController?
I want tabbar clicks to open directly to the UserProfileVewController rather than UserViewController which is login/signup viewcontroller.
In the project's AppDelegate, you could check if user is logged/registered or not, and display the ViewControllers dependently:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BOOL userIsLoggedIn = AMethodCheckIfUserLoggedIn();
if (userIsLoggedIn) {
UserProfileViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"UserProfileVewController"];
self.window.rootViewController = vc;
}
else{
UserViewController *userViewController = [storyboard instantiateViewControllerWithIdentifier:#"UserViewController"];
self.window.rootViewController = userViewController;
}
//... Other logic goes here
[self.window makeKeyAndVisible];
return YES;
}
You could try having your app delegate (or whomever you want really) conform to the UITabBarControllerDelegate and implement - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController. In there you might be able to do the necessary checks/fiddling of the view controllers maybe.

iOS - Transition between different Storyboard view controllers

I have divided my project into two storyboards:
Main.storyboard - For authenticated user. Also this is the default storyboard.
Login.storyboard - For non-authenticated user.
App delegate file:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(user is authenticated)
{
[self presentLoginScreen:YES];
return YES;
}
Login Screen in app delegate file:
-(void)presentLoginScreen:(BOOL)animated{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
}
On logout, login Screen is presented. I defined this in app delegate file:
-(void)logOut{
//clear data
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window.rootViewController = vc;
//Show login Screen
[self presentLoginScreen:NO];
}
From viewcontroller of MainStoryBoard(letsay mainstoryboardVc.m), logOut is called as:
-(void)didTouchLogOut{
NSLog(#"GoodBye");
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
[appDelegateTemp logOut];
}
This is causing a lot of issue:
Firstly, when I log out, and move to login screen, I can still see mainstoryboardVc.m in the background which looks very clumsy.
I log out, re-log in and again trying to log out, I see following message:
Presenting view controllers on detached view controllers is discouraged
and login screen is not presented.
I tried many answers on the web on view controller presentations between two storyboards without keeping history, nothing seems to work...
To swap out UIViewControllers there are a few other methods that need to be called when transitioning the root view controller:
Objective-c:
- (void)setRootViewController:(UIViewController *) newRootViewController {
UIViewController* currentViewController = self.window.rootViewController;
if (newRootViewController != currentViewController) {
[currentViewController willMoveToParentViewController:nil];
[currentViewController.view removeFromSuperview];
[currentViewController removeFromParentViewController];
self.window.rootViewController = newRootViewController;
}
}
Swift:
func setRootViewController(newRootViewController: UIViewController) {
if let currentViewController = self.window?.rootViewController {
if currentViewController != newRootViewController {
currentViewController.willMoveToParentViewController(nil)
currentViewController.view.removeFromSuperview()
currentViewController.removeFromParentViewController()
self.window?.rootViewController = currentViewController
}
}
}
Two UIViewController objects are duplicated because you set self.window.rootViewController for both of them. Try that;
Login
-(void)presentLoginScreen:(BOOL)animated{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
Logout
-(void)logOut{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Login" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
[self presentViewController:vc animated:YES completion:nil];
}

IOS: how to handle view controllers at first Login ios

When i first come to Login Screen I store value in NSUserDefaults. When I press on signinButtonAction to move to DetailScreen it stucks and never moves forward.
I have made DetailScreen embedded in Navigationcontroller as InitialViewController even the next screen is not navigating to other screens when i re-run it again it comes to DetailScreen and then DetailScreen stucks to navigate to other screens.
How do I handle this?
My code is here:
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"email"])
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
categoryVC *viewController = (categoryVC *)[storyboard instantiateViewControllerWithIdentifier:#"categoryVC"];
[self.window setRootViewController:viewController];
}
else
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
signInVC *viewController = (signInVC *)[storyboard instantiateViewControllerWithIdentifier:#"signInVC"];
[self.window setRootViewController:viewController];
}
in SigninButtonAction I am doing:
{
categoryVC * second= [self.storyboard instantiateViewControllerWithIdentifier:#"categoryVC"];
[self.navigationController pushViewController:second animated:YES];
}
I would not set RootViewController if you have such a workflow. I would instantiate main view controller as is, and if you need to show auth I would use presentViewController. Later on, you can do dismiss or something like that.
So, in you app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (nil == [[NSUserDefaults standardUserDefaults] objectForKey:#"email"])
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
categoryVC *viewController = (categoryVC *)[storyboard instantiateViewControllerWithIdentifier:#"signInVC"];
[self.window.rootViewController presentViewController:viewController animated:NO];
}
}
and then, when you do the auth and it passes:
[self dismissViewControllerAnimated:TRUE completion:nil];

How to set root view controller in storyboard animated with navigation controller programmatically

I have my login screen how ever i can able to skip that screen and go to home page when I am in the home page I could`d able to get my navigation controller in my home page i have embedded navigation controller with my login page have connectivity via push segue to home page every thing is good but nav bar is not coming in homepage if I try to embedded nav controller in homepage then also its not coming ... my code is
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:#"registered"])
{ NSLog(#"no user register ");
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
ViewController *secondViewController = [storyBoard instantiateViewControllerWithIdentifier:#"LoginPage"];
self.window.rootViewController = secondViewController;
// then set your root view controller
}
else
{ NSLog(#"user is daam sure registered");
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] ;
;
ABDB_CAMERAHOME *mainviewcontroller = [storyBoard instantiateViewControllerWithIdentifier:#"CameraHome"];
self.window.rootViewController = mainviewcontroller;
}
return YES;
}
is their I am missing constraint about nav controller in program please suggest
User following method to set rootViewController using navigation:
[(UINavigationController*)self.window.rootViewController pushViewController:yourViewController animated:YES];
In latest Xcode 6.1 in storyboards their are settings for navigation controller bar visibility. You can tick the "Shows Navigation Bar" for display.
In your appDelegate.h add below property and synthesize in .m
#property(strong,nonatomic)UINavigationController *navigationController;
#synthesize navigationController;
now modify app delegate as below
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:#"registered"])
{ NSLog(#"no user register ");
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
ViewController *secondViewController = [storyBoard instantiateViewControllerWithIdentifier:#"LoginPage"];
self.navigationController=[[UINavigationController alloc]initWithRootViewController:secondViewController];
self.window.rootViewController = self.navigationController;
// then set your root view controller
}
else
{ NSLog(#"user is daam sure registered");
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] ;
;
ABDB_CAMERAHOME *mainviewcontroller = [storyBoard instantiateViewControllerWithIdentifier:#"CameraHome"];
self.navigationController=[[UINavigationController alloc]initWithRootViewController:mainviewcontroller];
self.window.rootViewController = self.navigationController;
}
return YES;
}
Once all is set, check your storyboard whether you have mentioned proper xib identifier names over there? Also if you have used any navigation controller there, remove that also. Now clean the project from build setting and re-run.

access storyboard and nested UIViewControllers in appDelegate

How can I access storyboard as well as it's UIViewControllers inside the appDelegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
Try this :
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *uvc = [storyboard instantiateViewControllerWithIdentifier:#"Details"];
[self.window.rootViewController presentViewController:uvc animated:YES completion:nil];
For the case your UIViewController is named MyViewController and its storyboard has name MyViewController.storyboard, the code you've requested will look like this:
// load storybord with name MyViewController.storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MyViewController" bundle:nil];
// get an instance of root view controller for the storyboard
MyViewController *viewController = [storyboard instantiateInitialViewController];

Resources