Customize View Controller Stack on didFinishLaunching - ios

I am trying to present a tutorial/login/introduction view controller for my app on first launch using the following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
UIViewController *firstController = [[UIViewController alloc] init];
[self.window setRootViewController:firstController];
if ([self shouldShowIntro]) {
IntroViewController *introViewController = [[IntroViewController alloc] init];
[firstController presentViewController:introViewController animated:NO completion:nil];
}
return YES;
}
This works fine, but there is an annoying visual effect that takes place... Before you see the IntroViewController, there is a split second where the firstController is visible. I tried presenting the IntroViewController before setting the rootViewController of the window, but this (not surprisingly) results in the following warning:
Warning: Attempt to present <IntroViewController: 0x7fd8eb3362f0> on <UIViewController: 0x7fd8eb335180> whose view is not in the window hierarchy!
How can I modally present the IntroViewController without this annoying visual flash? I want IntroViewController to already be showing after the launch screen disappears and be able to be dismissed modally.

The following works for me with no flicker running on iOS 8.1 on an iPhone 6 and in the simulator. I used SDK version 8.1 and I think your SDK level is different because I got different warnings and results than you using your provided code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
UIViewController *firstController = [[UIViewController alloc] init];
firstController.view.backgroundColor = [UIColor blueColor];
[self.window setRootViewController:firstController];
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* modalViewController = [[UIViewController alloc] init];
modalViewController.view.backgroundColor = [UIColor grayColor];
[firstController presentViewController: modalViewController animated: NO completion: nil];
});
// dismiss after a few seconds..
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[firstController dismissViewControllerAnimated: YES completion: nil];
});
return YES;
}
Update with MMDrawerController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
MMDrawerController *drawerController = [[MMDrawerController alloc] init];
drawerController.centerViewController = [[UIViewController alloc] init];
drawerController.centerViewController.view.backgroundColor = [UIColor blueColor];
drawerController.rightDrawerViewController = [[UIViewController alloc] init];
drawerController.rightDrawerViewController.view.backgroundColor = [UIColor greenColor];
drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
drawerController.closeDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
[self.window setRootViewController:drawerController];
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* modalViewController = [[UIViewController alloc] init];
modalViewController.view.backgroundColor = [UIColor grayColor];
[drawerController presentViewController: modalViewController animated: NO completion: nil];
});
// dismiss after a few seconds..
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[drawerController dismissViewControllerAnimated: YES completion: nil];
});
return YES;
}
Also, per you comment it sounds as if having the pre-loaded view is key. Try invoking [firstController view] and [modalController view] before you present to ensure they're loaded.

try moving this line below the code where you set your view controllers.
[self.window makeKeyAndVisible];
something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UIViewController *firstController = [[UIViewController alloc] init];
[self.window setRootViewController:firstController];
if ([self shouldShowIntro]) {
IntroViewController *introViewController = [[IntroViewController alloc] init];
[firstController presentViewController:introViewController animated:NO completion:nil];
}
[self.window makeKeyAndVisible];
return YES
}

Put
if ([self shouldShowIntro]) {
IntroViewController *introViewController = [[IntroViewController alloc] init];
[firstController presentViewController:introViewController animated:NO completion:nil];
}
in to the viewDidAppear function of FirstViewController rather than in the AppDelegate. That should suppress the warning and perform the operation smoothly.

Related

How to set rootViewController for navigation view controller and tabbar controller in AppDelegate

i have this problem. When i set rootViewController for TabbarController, it show correctly. But i set another rootViewController for navigation bar, TabbarController will not able to display. Any idea?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[DCTabBarController alloc] init];
DCTabBarController *tabBar = (DCTabBarController *)self.window.rootViewController;
[tabBar setSelectedIndex:2];
Map_ViewController *vc = [[Map_ViewController alloc] init];
UINavigationController *rootNav = [[UINavigationController alloc] initWithRootViewController:vc];
[rootNav.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbarBackImage"] forBarMetrics:UIBarMetricsDefault];
rootNav.navigationBar.tintColor = [UIColor whiteColor];
[rootNav.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],NSForegroundColorAttributeName, nil]];
LeftViewController *leftVC = [[LeftViewController alloc] init];
RightViewController *rightVC = [[RightViewController alloc] init];
XLSlideMenu *slideMenu = [[XLSlideMenu alloc] initWithRootViewController:rootNav];
slideMenu.leftViewController = leftVC;
slideMenu.rightViewController = rightVC;
self.window.rootViewController = slideMenu;
[self.window makeKeyAndVisible];
return YES;
}
After applied Adeel solution, here is the output.But items in tabbar will not display accordingly.
One important thing to mention here is that an application's window can have only one rootViewController (of course). Like I said in my comment as well, you probably want to do something like this.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
Map_ViewController *vc = [[Map_ViewController alloc] init];
UINavigationController *rootNav = [[UINavigationController alloc] initWithRootViewController:vc];
[rootNav.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbarBackImage"] forBarMetrics:UIBarMetricsDefault];
rootNav.navigationBar.tintColor = [UIColor whiteColor];
[rootNav.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],NSForegroundColorAttributeName, nil]];
DCTabBarController *tabBar = [[DCTabBarController alloc] init];
[tabBar setViewControllers:#[rootNav]];
self.window.rootViewController = tabBar;
LeftViewController *leftVC = [[LeftViewController alloc] init];
RightViewController *rightVC = [[RightViewController alloc] init];
XLSlideMenu *slideMenu = [[XLSlideMenu alloc] initWithRootViewController:tabBar];
slideMenu.leftViewController = leftVC;
slideMenu.rightViewController = rightVC;
self.window.rootViewController = slideMenu;
[self.window makeKeyAndVisible];
return YES;
}

Switching root view controller

I've an app with UINavigationController already, but i want to switch to UITabBarController, the problem is when i switch to UItab from beginning it doesn't work, so i'm switching it in a delegate method but it doesn't work either!
all code in the app delegate.
self.navigationController = [[UINavigationController alloc] initWithRootViewController:[[UIViewController alloc] init]];
self.tabBarController = [[UITabBarController alloc] init];
if ([PFUser currentUser]) {
// Present wall straight-away
[self presentWallViewControllerAnimated:NO];
} else {
// Go to the welcome screen and have them log in or create an account.
[self presentLoginViewController];
}
[PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
The delegate method i want to switch on it:
- (void)presentWallViewControllerAnimated:(BOOL)animated {
NSLog(#"Called:presentWallViewControllerAnimated ");
// self.navigationController = nil;
self.tabBarController = [[UITabBarController alloc] init];
PAWWallViewController *wallViewController = [[PAWWallViewController alloc] initWithNibName:nil bundle:nil];
wallViewController.delegate = self;
// Set up the first View Controller
UIViewController *vc1 = [[UIViewController alloc] init];
vc1.view.backgroundColor = [UIColor orangeColor];
vc1.tabBarItem.title = #"Orange";
vc1.tabBarItem.image = [UIImage imageNamed:#"heart"];
// Set up the second View Controller
UIViewController *vc2 = [[UIViewController alloc] init];
vc2.view.backgroundColor = [UIColor purpleColor];
vc2.tabBarItem.title = #"Purple";
vc2.tabBarItem.image = [UIImage imageNamed:#"star"];
// Set up the Tab Bar Controller to have two tabs
[self.tabBarController setViewControllers:#[ vc1, vc2]];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
// [self.window addSubview:tabBarController.view];
// [self.navigationController setViewControllers:#[ tabBarController ] animated:animated];
}
Remember to handle the view transition:
UIViewController *vc = // any vc that's initialized properly
window.rootViewController = vc;
[UIView transitionWithView:window
duration:0.3 // 0.0 for immediate
options:UIViewAnimationOptionTransitionCrossDissolve // several enums to choose from here
animations:nil
completion:nil];
and you don't need makeKeyAndVisible after the first time.
You called - (void)presentWallViewControllerAnimated:(BOOL)animated but in the end of didFinishLaunchingWithOptions you called
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
So the tab bar will never works !

How can i connect UITableView to my Appdelegate.m?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MainViewController *rootViewController = [[MainViewController alloc] init];
_naviControl = [[UINavigationController alloc]initWithRootViewController:rootViewController];
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[self.window addSubview:_naviControl.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
In my AppDelegate ..!
Connect to MainViewController.m
The AppDelegate is not a UIViewController so connecting a UITableView to it conflicts with the MVC principles as described here: https://developer.apple.com/library/ios/documentation/general/conceptual/devpedia-cocoacore/MVC.html
what you want to do is make your MainViewController's view have a tableView as a subview
something like this:
(in MainViewController.m)
- (void)viewDidLoad {
[super viewDidLoad];
self.feedTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.feedTableView.dataSource = self;
self.feedTableView.delegate = self;
[self.view addSubview:self.feedTableView];
}

Can't pop iOS viewController. Not sure, but I think it's something with the Navigation Controller

I'm having trouble trying to pop a view
App Delegate
#implementation MAAppDelegate
#synthesize navController;
#synthesize detailViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Init the navController for the Master Detail View of the grade cells
UINavigationController *navController = [[UINavigationController alloc] init];
detailViewController = [[UIViewController alloc] init]; //step6
navController = [[UINavigationController alloc] initWithRootViewController:[[MAController alloc] init]]; //step7
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = navController; //step8
[self.window makeKeyAndVisible];
// Set MAController as rootViewController
//self.window.rootViewController = [[MAController alloc] init];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
// Use the insanely cool TSMessages to show network alerts
[TSMessage setDefaultViewController: self.window.rootViewController];
return YES;
}
First part of viewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.navigationController setNavigationBarHidden:YES];
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Home" style:UIBarButtonItemStyleBordered target:self action:#selector(home:)];
self.navigationItem.leftBarButtonItem=newBackButton;
Later, when I change the viewController
NSLog(#"Opened progress report");
UIViewController *detailViewControl = [[UIViewController alloc] init];
// Set progress report as the view controller
[self.navigationController pushViewController:detailViewControl animated:YES];
UIImage *background = [UIImage imageNamed:#"bg"];
// Add static image bg
self.backgroundImageView = [[UIImageView alloc] initWithImage:background];
self.backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
[self.view addSubview:self.backgroundImageView];
// Add blurred layer to image when tableView goes in front of it
self.blurredImageView = [[UIImageView alloc] init];
self.blurredImageView.contentMode = UIViewContentModeScaleAspectFill;
self.blurredImageView.alpha = 0;
[self.blurredImageView setImageToBlur:background blurRadius:10 completionBlock:nil];
[self.view addSubview:self.blurredImageView];
[self.navigationController setNavigationBarHidden:NO];
So I don't understand why that when I do this, a selector from the button (that I know fires, because I get Righthtere in my log):
-(void)home:(UIBarButtonItem *)sender {
NSLog(#"Righthtere");
// Set progress report as the view controller
[self.navigationController popToViewController:self animated:YES];
}
It doesn't go back to the initial view controller.
You seem to be confusing popToViewController and popViewControllerAnimated. popViewControllerAnimated removes the current view from the stack and brings the new stack top the active view controller. popToViewController pops the stack until the listed view controller is on top of the stack.
Since you are calling popToViewController with self, it will look and see that the requested view controller is already on top of the stack and do nothing. If you wish to go back one view controller then your call should be.
[self.navigationController popViewControllerAnimated:YES];
I use the below code to pop the previous viewcontroller in iOS 8.
[self presentModalViewController:viewcontroller animated:YES];

App crashes on iPhone 5 when calling the Viewcontroller in delegate

I have a project that works well in other simulators including The New iPad. However, with the iPhone5, it crashes when calling the Viewcontroller in delegate
I don't know why this error happens. Please let me know if you discover any possible causes in the code below:
self.rootviewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
self.rootNavController = [[UINavigationController alloc]
self.rootNavController.navigationBar.hidden=YES;
[window addSubview:rootNavController.view];'
Please see image below:
Thank you very much
I think you do something wrong with the creation of your UINavigationController, try the following code to replace yours in your AppDelegate.m :
EDIT add code to display and remove splashscreen with UIViewController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create View Controller
RootViewController *rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
// Create Navigation Controller
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
// Create Navigation Controller
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
// SplashScreen
[self displaySplashscreen];
return YES;
}
#pragma mark - SplashScreen Methods
- (void)displaySplashscreen
{
// Create View
self.splashscreenViewController = [[SplashscreenViewController alloc] init];
// Display Splashscreen
[_window addSubview:_splashscreenViewController.view];
// Dismiss Splashscreen
[self performSelector:#selector(dismissSplashscreen) withObject:nil afterDelay:3.0f]; // Modify the time
}
- (void)dismissSplashscreen
{
// Splashscreen Animation
[UIView animateWithDuration:0.5f
animations:^{
_splashscreenViewController.view.alpha = 0.0f;
} completion:^(BOOL finished) {
[_splashscreenViewController.view removeFromSuperview];
}];
}

Resources