I started with a GLSprite sample app (source code), then added a UIViewController by adding
UIViewController *vc = [[UIViewController alloc] init];
vc.view = glView;
self.window.rootViewController = vc;
[window makeKeyAndVisible];
to the end of GLSpriteAppDelegate::applicationDidFinishLaunching. The controller seems to be working as now I can pop up gamecenter windows, but it has messed up my screen orientation. The app is fine in portrait, but in all other rotations it incorrectly has white bars on the side, like one of the views is rotated 90 degrees.
I was doing [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; in EAGLView::initWithCoder, I then tried moving it to the end of applicationDidFinishLaunching but it had the same behavior.
Can anyone help? What can I do to fix or debug this? Thank you!
The issue was the new UIViewController was rotating, when my game expects an always portrait screen. To fix I created a custom viewcontroller and implemented
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return 0;
}
Related
I have a view controller which I want to lock down in portrait mode. By creating a custom navigation controller I have been able to force portrait mode when the device is in landscape, and that works initially when the app starts up.
But when I rotate the device to portrait mode and then back to landscape, the orientation changes again.
I would assume that shouldAutorotate returning NO should prevent this, but it doesn't for some reason. I verified that function is being called every time I physically rotate the device.
Anyone know why iOS is ignoring my shouldAutotate of NO?
I've read many posts on this and my code seems to be what many people are suggesting, but doesn't work.
#interface MyUINavigationController : UINavigationController
#end
#implementation MyUINavigationController
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait ;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
NSLog(#"shouldAutorotate called and returning NO");
return NO;
}
#end
// This is how I am using my custom Navigation Controller:
UINavigationController* mynav = [[MyUINavigationController alloc] initWithRootViewController:customViewController];
visibleVC = [[[UIApplication sharedApplication] keyWindow] rootViewController];
[mynav setModalPresentationStyle:UIModalPresentationFullScreen];
[mynav setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[visibleVC presentViewController:mynav animated:YES completion:nil];
I'm new to stackoverflow and to objective-C programming. I have searched for the issue described below, but I'm not able to find a working solution.
My application is a simple offline browsing app, with navigation structure.
In the appDelegate I load the RootViewController (UITableViewController) in one of the following ways:
Solution A
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
Solution B
RootViewController* rootviewcontroller = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:rootviewcontroller];
The rootViewController simply push some views, i.e.
TipAndTrickViewController *mTipAndTrick = [[TipAndTrickViewController alloc]initWithNibName:#"TipAndTrickViewController" bundle:nil];
[self.navigationController pushViewController:mTipAndTrick animated:YES];
In the deeper view I present a detail modalView (UIViewController).
What I want is to enable autorotate only in this last view. The portait orientation is the desired for all the previoues wiews. The last view implements in the right way:
shouldAutorotateToInterfaceOrientation:interfaceOrientation
shouldAutorotate
willRotateToInterfaceOrientation:toInterfaceOrientation
duration:duration
willAnimateRotationToInterfaceOrientation:interfaceOrientation
duration:duration
Overriding
shouldAutorotate
shouldAutorotateToInterfaceOrientation:interfaceOrientation
making them returning NO/YES in the rootViewController and setting the allowed orientation in the desired way, using
supportedInterfaceOrientations
(both in rootViewCOntroller and in the last view), I get those results:
if I use Solution A all the views don't rotate.
if I use Solution B all the views always rotate.
What I'm doing in the wrong way?
Thank you in advance for your help
Add these to your viewController and let me know if it works or not .
// iOS5 Rotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
// iOS6 Rotation
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate
{
return YES;
}
I just opened my iPad project on XCode 4.5. My app is designed to run in Landscape mode. It works perfectly on previous versions of XCode. But on XCode 4.5, it is rotated of 90° (quarter turn) with a empty area on the right side of the screen (and my view has the correct size but goes out of the screen). It looks like this:
I checked the following posts but didn't help:
orientation issue in ios6
ios6 Rotation issue from landscape to portrait mode
Set orientation to landscape mode in xcode 4.5 GM IOS 6
Anybody had this issue ?
Any help would be appreciated !
Thanks everybody for your replies. I finally found a solution.
First, check that all your launch images have the correct orientation and correct size in the target summary menu (blue icon of your project => target => summary => scroll at the bottom) ; if the size or orientation is not correct, you get a warning on the launch image which is not set properly.
Up to now, I had a project with this structure (old XCode fashion):
AppDelegate.h and .m
RootViewController.h and .m
a MainWindow-Iphone.xib and MainWindow-iPad.xib (with the RootViewController linked in Interface Builder ; see the screenshot below with the yellow/brown icon (with a square inside) relative to the RootViewController)
Here below a screenshot of what it looked like:
And here is what was the code in the applicationDidFinishLaunching: method of my AppDelegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[rootViewController view]];
[window makeKeyAndVisible];
}
What I did is to be closer to the structure you get when you create an empty project with XCode 4.5. Consequently:
I removed the MainWindow.xib and MainWindow-iPad.xib and now created my window programatically (clearer and better to make sure that it fits the size of any screen)
I removed the "Main nib file base name" and "Main nib file base name (iPad)" keys which were defined in my Info.plist (and set to MainWindow.xib and MainWindow-iPad.xib)
I added empty RootViewController_iPhone.xib and RootViewController_iPad.xib
I changed the code in my applicationDidFinishLaunching method like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSLog(#"applicationDidFinishLaunching");
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController_iPhone" bundle:nil];
} else {
self.rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.rootViewController;
[self.window makeKeyAndVisible];
}
And now, everything works fine ! Orientation is correct on iPad ! And it is much more clear than before :) I even didn't have to change the deprecated methods like
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
By the way, to make sure that all your views will be full screen (on iPhone 5) make sure that your views are set to the mode "Scale to fill" in Interface Builder and that "Autoresize subviews" is clicked. If some of your views do not scale to full screen, it is probably due to the order in which one you create your controllers/views (the superView sends a notification to its subviews only when it (the superView) is created). To solve this easily, simply add the following code in the - (void)viewDidLoad method:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
[self.view setFrame:CGRectMake(0,0,screenBounds.size.width,screenBounds.size.height)];
or use:
[self presentModalViewController:myViewController animated:TRUE];
instead of:
[self.view.superview addSubview:myViewController.view];
presentModalViewController indeed sends a resizing notification to the subviews.
Hope this will help !
Make sure you are setting the window.rootViewController as well. I had the same issue, but this line fixed it for me:
MainViewController *mainView = [[MainViewController alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = mainView;
I had a similar problem on an app I upgraded. I haven't found it documented but it seems there has been a change. What I ended up finding is the new window doesn't seem to know about rotation or size until after it is made key and visible. I was able to move my frame setting to immediately after makeKeyAndVisible and everything worked. I hope that helps you.
[[yourViewController view] setFrame:CGRectMake(0.0, 0.0, 1024.0, 768.0)];
[[yourViewController view] setTransform:CGAffineTransformTranslate(CGAffineTransformMakeRotation(0.5*M_PI),128.0,128.0)];
If you are using Storyboards one easy hack is to use the loadView method. It is called before viewDidLoad. Just go to your Storyboard and delete the associated view as you are going to create it programmatically in loadView. Then return to the view controller class and copy the following code:
- (void)loadView
{
// You can adjust the view size and location here. If using full screen use the following code. If you have a tab bar for example and also want to account for the top default iPad bar, use: CGRectMake(0, 20, 1024, 699) instead.
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 748)];
view.backgroundColor = [UIColor whiteColor];
view.autoresizesSubviews = NO;
self.view = view;
}
A few simple steps in order will solve this problem for you.
First, in AppDelegate.m, check if you're adding your rootViewController as a subView. That is, instead of this,
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
do something like this
- (void)applicationDidFinishLaunching:(UIApplication *)application {
window.rootViewController = navigationController;
[window makeKeyAndVisible];
}
if you're setting a navigation controller as your root view controller.
Second, if you need to get control of the rotation methods within your navigationController's pushed viewControllers, create a category for UINavigationController like so:
#import "UINavigationController+Rotation.h"
#implementation UINavigationController (Rotation)
- (BOOL)shouldAutorotate {
BOOL result = self.topViewController.shouldAutorotate;
return result;
}
- (NSUInteger)supportedInterfaceOrientations {
return self.topViewController.supportedInterfaceOrientations;
}
#end
Now, these two orientation methods for iOS 6 upwards
-(BOOL)shouldAutorotate and
-(NSUInteger)supportedInterfaceOrientations
will get called within your classes.
This is necessary because the older rotation methods such as
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
have been deprecated from iOS 6.
So lastly, you'll need to implement these in your view controllers; something like this:
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
if you want to allow your view controller to rotate and support all orientations.
The other orientation masks are:
UIInterfaceOrientationMaskPortrait
UIInterfaceOrientationMaskLandscapeLeft
UIInterfaceOrientationMaskLandscapeRight
UIInterfaceOrientationMaskPortraitUpsideDown
UIInterfaceOrientationMaskLandscape and
UIInterfaceOrientationMaskAllButUpsideDown
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;
I have another orientation problem. But this one is very tricky.
My RootViewController is a normal NavigationController.
self.window.rootViewController = _naviController;
which has another ViewController inside, lets call it VC1.
VC1 has some buttons and labels. Its like an overview with folders.
If I press a button I come to the next ViewController with 3 ViewController (Page) and another bunch of buttons (like inside a folder looking at the pictures/thumbnails inside):
Archiv *archiv = [[Archiv alloc] init];
[self.navigationController pushViewController:archiv animated:YES];
[archiv release];
in loadView:
firstPage = [[Page alloc] initViewWithFrame:CGRectMake(0, 0, 768, 960)];
[firstPage setRootViewController:self];
secondPage = [[Page alloc] initViewWithFrame:CGRectMake(0, -960, 768, 960)];
[secondPage setRootViewController:self];
thirdPage = [[Page alloc] initViewWithFrame:CGRectMake(0, 960, 768, 960)];
[thirdPage setRootViewController:self];
If I now click again on a button the active Page push my third ViewController (image with resizing, dragging...):
Picture *pic = [[Picture alloc] initWithPicURLString:urlString];
[rootViewController.navigationController pushViewController:pic animated:YES];
[pic release];
With the BackButton of the NavigationController I can always come back to the previous view.
Some more informations:
Every ViewController supports all orientations
Every ViewController implements - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation with return YES;
Every ViewControler calls the [super init] in their init-methode
I already read Apple's Q&A: Why won't my UIViewController rotate with the device
Now the tricky problem:
If I switch from 2nd VC to the 3rd VC, change the orientation there from portrait to landscape and press the BackButton everything is working (shouldAutorotateToInterfaceOrientation is calling, frame size and origins changing ...).
BUT if I do it the other way around, I am in landscape mode, switch from 2nd VC to 3rd VC, rotate to portrait and come back to 2nd VC with BackButton, the status- and controllerBar are at the top but the shouldAutorotateToInterfaceOrientation wasn't called.
Please help me. $h#rky
Try this, it works for me:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self shouldAutorotateToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation] ];
}
Today I got the idea that solved the problem without knowing the cause.
In my third VC I just created a pointer to the 2nd View and called the shouldAutorotateToInterfaceOrientation myself.
But the point is still the same: Why isn't shouldAutorotateToInterfaceOrientation not calling in the described situation?
Kind regards. $h#rky
shouldAutorotateToInterfaceOrientation only called when user rotate, so when you from landscape to portrait or otherwise then view controller still landscape, so this solve problem, you have to hack code, it's mean when you push to view controller from landscape to portrait presentViewController example:
ListCurrentViewController *list = [self.storyboard
instantiateViewControllerWithIdentifier:#"ListCurrentViewController"];
[self.navigationController presentViewController:list animated:NO completion:Nil];
[list dismissViewControllerAnimated:NO completion:Nil];
[self.navigationController pushViewController:list animated:YES];
in ListViewController function called:
(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation // iOS 6 autorotation fix { return UIInterfaceOrientationPortrait; }
and you have to create category for UINavigationController
(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.visibleViewController preferredInterfaceOrientationForPresentation];
}
I hope this solve will help you.