I am developing an iOS application which needs to be launched with different rootViewControllers (for example if the user had already registered, or if it started after a local notification), and these viewControllers are in different storyboards. I thought one way to do this, is to leave the Main interface field blank in the Deployment info, and configure the rootViewController manually.
I set the rootViewController in my application delegate class:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
IDOptionsViewController *mainViewController = [storyboard instantiateViewControllerWithIdentifier:#"options"];
self.window.rootViewController = mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
When I launch the application, the rootViewController appears, but it does not respond to any user interaction (I tested the viewController, it works fine other places).
I'm new to Objective-C and iOS, so I'm not sure I even understand storyboards correctly.
I'm using iOS SDK 7.1, Xcode 5.
Thanks for the answers.
I had the same problem. In may case the root UIViewController called
[[UIApplication sharedApplication] beginIgnoringInteractionEvents]
So, make sure user interaction events are enabled by calling [UIApplication sharedApplication].isIgnoringInteractionEvents]. To enable user interaction events call [[UIApplication sharedApplication] endIgnoringInteractionEvents].
Related
So the problem is--and this is new, this used to work in iOS 7-- when I comment out "FinishedLaunching", it rotates just fine but when I override this "FinishedLaunching" function to create the "window" myself, it fails to rotate. This is really strange. Any thoughts?
The reason I want to use FinishedLunching is because sometimes I want a different viewController to be the initial view controller.
Here is the code in my "FinishedLunching"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
The problem is that you are creating a new window with
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
when the AppDelegate one that it automatically sets up for you that is perfectly fine to use, just use self.window without alloc-initing a new one
My app consists of a navigation controller and view controllers. Some parts of my UI is done on storyboard and some are initiated from code (in viewDidLoad). My goal is to load childViewController X (consists of a back button, nag bar, label and table) when the app is launched from a push notification "properly" through this method in appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
This might be a simple question to you guys but I've asked several questions the pass few days (you can look at my questions history). After trying several methods, my app either:
crashes
loads without navigation bar
loads with navigation bar but no label (back button does not work)
loads with navigation bar but with black screen underneath
Only the tableView is dragged onto storyboard. The navigation bar is inferred but I have code that dictates its back button and title. The rest is all done through code in the .m file.
I know people have asked this question before but none of the methods worked. How can I load this childViewController properly through a push notification?
EDIT/UPDATE:
My code so far:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* firstVC = [mainstoryboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
[self.window.rootViewController addChildViewController:firstVC];
[(UINavigationController *)self.window.rootViewController pushViewController:firstVC animated:NO];
self.window.rootViewController.childViewControllers);
}}
Error Code:
'-[SWRevealViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14575f20'
SWRevealViewController is my library for my sidebar menu view controller.
UPDATE2:
I've also tried this method:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initViewController;
[self.window makeKeyAndVisible];
This loads the correct viewController but without a navigation bar.
Try this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(dictionary != nil) {
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *firstVC = [mainstoryboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
// Navigation already created
if(navigationController) {
[navigationController pushViewController:firstVC animated:NO];
// Navigation not created
} else {
UINavigationViewController *navigationController = [[UINavigationViewController alloc] initWithRootController:firstVC];
[self.window setRootViewController:firstVC];
[self.window makeKeyAndVisible];
}
}
return YES;
}
You had some problem in your code:
You need to have a UINavigationController in order to have a navigation bar and manage the push/pop actions, so your window root controller should be a UINavigationController.
If you need to initialize a UINavigationController the best and simple way is to initialize it with a root controller directly, so leave the push/pop for user actions: an application has always a root controller, so why don't you create it immediately?
The "addChildController" is another thing: it is used to create custom container controller, it means that you have to implement all the business logic manually. I suggest you to use it only if you are experienced enough, since it could be difficult - Cocoa has enough components to leave it for a small set of applications.
You are using a third part controller, the "SWRevealViewController". They should have an example project, you can try to "copy" it and them customize it for your own purpose.
Let me know if your code works well, otherwise post the new error and I'll try to help you
I understand this question is many times on STackOverflow and also many on internet too. I have also asked question related to be same, but the context is different, so please bear with me as I am not able to find the solution for this task.
I am using Xcode 5, using Storyboard. MY project is Tab based and have added a LoginViewController in the storyboard. My win is to show LoginViewController prior to Tabs. I tried several ways from various sites, but nothing works fully. With this code, I could get the LoginViewController at first, but not able to get Tabs controller. In my AppDelegate :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
self.tabBarController = [[MC_MainTabBarController alloc] init];
LoginViewController *loginViewController = [storyboard instantiateViewControllerWithIdentifier:#"loginViewController"];
[self.window setRootViewController:loginViewController];
// This also works - it shows the login
//[[[[UIApplication sharedApplication] delegate] window] setRootViewController:loginViewController];
// With this Login doesn't come only
//[loginViewController setModalPresentationStyle:UIModalPresentationFullScreen];
//[tabCtrler presentViewController:loginViewController animated:NO completion:nil];
return YES;
}
In my LoginViewController.m - on loginBtnClicked event in end, I call :
NSLog(#"Showing TabController");
MC_AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate.window setRootViewController:appDelegate.tabBarController];
On execution of the above lines, I get black screen and following warning :
Showing TabController
Two-stage rotation animation is deprecated. This application should use the smoother single-stage animation.
Two-stage rotation animation is deprecated. This application should use the smoother single-stage animation.
Can anyone please help me out. I am stuck on this problem from last 2 days.
Any help is highly appreciated.
Are you sure MC_MainTabBarController is a subClass of UITabBarController? (I guess it is)
because this error can appear when the TabBar is not the rootViewController
Instead of [[MC_MainTabBarController alloc] init]; i would allocated the tab bar controller from storyboard [storyboard instantiateViewControllerWithIdentifier:#"myTabBarIdentifier"];
I try and it worked for me :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
_tabController = [storyboard instantiateViewControllerWithIdentifier:#"tabbcontrolllerid"];
LoginViewController *login = [[LoginViewController alloc]initWithNibName:#"LoginViewController" bundle:nil];
[_window setRootViewController:login];
return YES;
}
And like you in the button of login
- (IBAction)goToApp:(id)sender {
stackAppDelegate *app = [UIApplication sharedApplication].delegate;
[app.window setRootViewController:app.tabController];
}
For info the tab bar is a custom TabBarController which is a subclass of UITabBarController
And i have set in the storyboard the identifier of my custom tabbar.
I have a problem with my iOS app. It is based on storyboards. So to set the rootViewController property it should be enough to set the "Initial View Controller" property in Interface Builder and the MainInterface-Property in the project settings to the name of my storyboard. Still I always get the message "Application windows are expected to have a root view controller at the end of application launch".
I do several things in the applicationDidFinishLaunching section but even if everything except return YES; is commented out, I get the message.
How can I fix this warning? Or can I ignore it as everything works?
Thanks a lot.
Are you using an activity indicator in your app delegate or root view controller by chance? If so, it might be setting itself as the root. Move the display of the indicator to somewhere after your main views are set up.
Try this code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
InitialViewController initial = [self.storyboard instantiateViewControllerWithIdentifier:#"STORYBOARDID"];
window.rootViewController = initial;
[window makeKeyAndVisible];
return YES;}
I am developing a xib-based landscape-only app. The app launches in landscape correctly. However, the view in my main ViewController is presented in portrait. That is, it is rotated 90 degrees so that the image appears cropped and does not take up the entire screen. If I use my interface to present a modal view controller then return to the main ViewController, the issue corrects itself (the view is presented in landscape). This problem did not occur under Xcode 4.2. It occurred after upgrading to Xcode 4.3, and the only code changes that were made were automatically implemented by Xcode when I upgraded the project settings.
Based on advice in other posts, I verified my Info.plist settings for Supported Interface Orientations and Initial Interface Orientation. I overrode the shouldAutorotateToInterfaceOrientation method for each of my view controllers to return YES only for landscape orientations. Also, I turned off auto resizing for the view, as I never want the size/orientation of the view to change.
Based on the ideas in this link [1], I suspected the problem is that the view is not receiving the call to change orientation at launch, possibly due to the removal of the MainWindow.xib concept, which appears to be replaced by the following Xcode-inserted code in AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
I modified this method to generate a generic root view controller from which my ViewController class is presented, as shown in the code below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController* myViewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.viewController = [[UIViewController alloc] init];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
[self.viewController presentModalViewController:myViewController animated:NO];
return YES;
}
Voila! This solved my problem. However, to me it feels like a change at a fundamental level, which I don't want to make at this point in my development. What I intended to be my root view controller is now a modal view. Does anyone have another solution to this issue?
Thanks in advance!
I had this same issue: an app which was meant to be in Landscape that assumed the ViewController was always in Portrait. I made tons of changes to every aspect of the project and info.plist, including giving the main UIWindow a root-view controller which was landscape. It still didn't work. I eventually undid all the changes and just added the two lines noted below to my app delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
[_window addSubview:[_viewController view]];
glView = _viewController.glView;
// THIS FIXED ORIENTATION FOR ME IN IOS 6
_window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
// END
...my other setup code here...
}
Nothing else was necessary.
It appears that, for some reason, in iOS 6 the UIWindow root-view-controller setting is sometimes ignored in Interface Builder. I am sure my reasoning is wrong somewhere, but I thought this might well help prod someone in the direction of a fuller, more exhaustive answer.
In iOS 8, settings windows frame to the UIScreen is also necessary, as it won't get automatically updated.
self.window.frame = [UIScreen mainScreen].bounds;