I need to load storyboard programmatically, in iOS7 the following code works:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // need to comment out in iOS8
self.window.backgroundColor = [UIColor cyanColor];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];
[self.window makeKeyAndVisible];
return YES;
}
But in iOS8 (XCode 6.1), the above code doesn't auto rotate correctly:
and
I need to comment out self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; to correct the auto rotation.
Any idea that first line makes what different?
Well, I find the answer from developer forum. Just remove the UIMainStoryboardFile key from app's information property list.
"Your application's information property list contains the UIMainStoryboardFile key but you are also manually creating a UIWindow with a storyboard loaded manually in your app delegate.
When the UIMainStoryboardFile key is present in the information property list, the system creates a UIWindow object with the initial view controller from the storyboard corresponding to the value of the UIMainStoryboardFile key prior to calling your app delegate. Your app delegate then repeats this process, determining which storyboard to load based on the screen size, and creating another UIWindow with the initial view controller from the storyboard.
The window created by the system, being the first window, receives orientation change notification first. Due to a change in iOS 8.1, the first window ends up blocking the second window (the one you created, the key window) from responding to the orientation change. From what I have discerned, this only happens if the first windows rootViewController's view is not loaded (the original window is never made visible). I'm clarifying the details with engineering and will log any needed bug reports myself.
The solution for your app is to remove the UIMainStoryboardFile and UIMainStoryboardFile~ipad keys from your app's information property list."
Related
Full disclaimer- I'm pretty new to iOS. I created a tableview with custom cells using the storyboard with a navigation controller as the initial entry point, and my tableview as the navigation controller's root view. When I run the app in the simulator, it seems as though everything is oversized/zoomed in, though my storyboard looks like this:
I've tried with iPad and iPhone and in both devices my story board doesn't pop up properly. I instantiate my root view controller thus:
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//get a pointer to my main storyboard
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
//instantiate my nav controller + item controller through the storyboard
UINavigationController *nav = [mainStoryBoard instantiateViewControllerWithIdentifier:#"navStoryBoard"];
ItemsViewController *ivs = [mainStoryBoard instantiateViewControllerWithIdentifier:#"tableStoryBoard"];
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window = window;
self.window.backgroundColor = [UIColor clearColor];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
Why won't my tableView appear in the correct size when I run my app? Am I instantiating my views incorrectly?
From the screenshot it looks like you are using Size classes (which is usually enabled by default). And hence the zoomed or scaled up behaviour.
If you are developing for a particular form factor, you may disable the "Use Size Class" property of the View Controller. More details here: https://developer.apple.com/library/ios/recipes/xcode_help-IB_adaptive_sizes/chapters/EnablingAdaptiveSizeDesign.html
However, if you want your UI to be scalable on different form factors - you should keep this checked and use Autolayout constrains for your Table View. More details here: https://developer.apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/UnderstandingAutolayout.html
I want to create my storyboard manually in code rather than have it load automatically, so I first removed the launch storyboard in the plist like so:
With this in my app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController * initalViewController = [storyboard instantiateInitialViewController];
UIWindow *window = [[UIWindow alloc] init];
[window setRootViewController:initalViewController];
[window makeKeyAndVisible];
self.window = window;
return YES;
}
The initial view controller loads correctly and is visible, however it does not get any touch events. I even set a breakpoint on touchesBegan. Does anyone know why the touches are not being delivered?
You have created your window with no frame, which will mean it actually has a frame of {{0, 0}, {0, 0}}. Views can not receive touches that are outside of their parents bounds therefore with a zero frame everything is out of the windows bounds.
You should probably update to something like this
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
See the note from the UIWindow docs (emphasise my own)
Note:
When you use storyboards and the Xcode app templates to create an app, a window is created for you. If you choose to create a window in Interface Builder, be sure to select the Full Screen at Launch option in the Attributes inspector so that the window is sized appropriately for the current device. Because a window doesn’t receive touch events outside of its bounds and views aren’t clipped to the window’s bounds by default, an improperly sized window might not be able to deliver touch events to all its views.
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 wanted to get rid of the storyboard and make everything in nib files. So I removed the main story board and coded the launch routine in the app delegate. I also deleted the storyboard name in the summary section of the app target so the complier won't complain. However, now nothing is shown when the app is launch, only a black blank screen. Is there away to fix this without creating a new non-storyboard project?
Here is the code in my app delegate..
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MasterViewController *mainController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] init];
[navController pushViewController:mainController animated:YES];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
return YES;
}
Edit your Info.plist to indicate the main nib file and not a storyboard file. You'll need to change both the key (UIMainStoryboardFile to NSMainNibFile) and the associated value.
When you deleted the main story board you also deleted the StoryBoard Entry Point. To fix this, replace the StoryBoard Entry Point and you should get the desired display.
Thanks,
Rajat
StoryBoard Entry Point
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;