I've been writing my Universal application in portrait mode,
and now after about 15 nib files, many many viewCotnrollers,
I'd like to implement the shouldAutorotateToInterfaceOrientation and design some screens in Landscape mode.
adding :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
to ALL of my viewControllers, does not do the work.
During Debug, i see that this method is called, but it just won't work! not in the simulator, not in the device, not in Iphone, not in Ipad!
i've searched some answers in the forum, and saw some advises to use:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown );
}
Didn't worked either,
adding:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
and
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
to my viewDidLoad and viewDidUnload respectively didn't worked either.
I'm lost.. Any help will do!
just one more info... all my Views are of type UIControl, as i needed the TuchUpInside to work.
Appriciate your help.
Make sure all of your parent views have autoresizesSubviews = YES. You may need to do this in code if you haven't set springs and struts in IB for all of your views.
Quoting the Interface Builder User's Guide:
Important: In a Cocoa nib file, if you
do not set any springs or struts for
your view in Interface Builder but
then do use the setAutoresizingMask:
method to add autosizing behavior at
runtime, your view may still not
exhibit the correct autoresizing
behavior. The reason is that Interface
Builder disables autosizing of a
parent view’s children altogether if
those children have no springs and
struts set. To enable the autosizing
behavior again, you must pass YES to
the setAutoresizesSubviews: method of
the parent view. Upon doing that, the
child views should autosize correctly.
A couple other things to be aware of:
A UINavigationController will only autorotate if its root view controller is also set to autorotate.
A UITabBarController will only autorotate if all of its view controllers are set to autorotate.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
UIInterfaceOrientation des=self.interfaceOrientation;
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad) //iPad
{
if(des==UIInterfaceOrientationPortrait||des==UIInterfaceOrientationPortraitUpsideDown)//ipad-portairait
{
}
else//ipad -landscape
{
}
}
else//iphone
{
UIInterfaceOrientation des=self.interfaceOrientation;
if(des==UIInterfaceOrientationPortrait||des==UIInterfaceOrientationPortraitUpsideDown) //iphone portrait
{
}
else //iphone -landscape
{
}
}
return YES;
}
Which iOS are you building for? It was deprecated in iOS 6.0. (You should override the supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation methods instead.)
Also you can call shouldAutorotate on the UIViewController class:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/shouldAutorotate
Ensure you have checked the Supported Interface Orientations within the "Summery" tab of the project settings (Select the project name in the 'Project Navigator' at the very top).
If you have not selected the orientations you want to use here, then the simulator/iphone will not allow the screen to change orientation.
I had this problem but it worked in iOS6 but not iOS5. Turns out I had a view in my storyboard that I hadn't made a viewcontroller class for yet.
...and last but not least, make sure you haven't activated the setting "Portrait Orientation Locked" on your test device (of course doesn't apply to the simulator), this will disable rotating in any app no matter what shouldAutorotateToInterfaceOrientation returns.
Related
I've been writing my Universal application in portrait mode,
and now after about 15 nib files, many many viewCotnrollers,
I'd like to implement the shouldAutorotateToInterfaceOrientation and design some screens in Landscape mode.
adding :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
to ALL of my viewControllers, does not do the work.
During Debug, i see that this method is called, but it just won't work! not in the simulator, not in the device, not in Iphone, not in Ipad!
i've searched some answers in the forum, and saw some advises to use:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown );
}
Didn't worked either,
adding:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
and
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
to my viewDidLoad and viewDidUnload respectively didn't worked either.
I'm lost.. Any help will do!
just one more info... all my Views are of type UIControl, as i needed the TuchUpInside to work.
Appriciate your help.
Make sure all of your parent views have autoresizesSubviews = YES. You may need to do this in code if you haven't set springs and struts in IB for all of your views.
Quoting the Interface Builder User's Guide:
Important: In a Cocoa nib file, if you
do not set any springs or struts for
your view in Interface Builder but
then do use the setAutoresizingMask:
method to add autosizing behavior at
runtime, your view may still not
exhibit the correct autoresizing
behavior. The reason is that Interface
Builder disables autosizing of a
parent view’s children altogether if
those children have no springs and
struts set. To enable the autosizing
behavior again, you must pass YES to
the setAutoresizesSubviews: method of
the parent view. Upon doing that, the
child views should autosize correctly.
A couple other things to be aware of:
A UINavigationController will only autorotate if its root view controller is also set to autorotate.
A UITabBarController will only autorotate if all of its view controllers are set to autorotate.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
UIInterfaceOrientation des=self.interfaceOrientation;
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad) //iPad
{
if(des==UIInterfaceOrientationPortrait||des==UIInterfaceOrientationPortraitUpsideDown)//ipad-portairait
{
}
else//ipad -landscape
{
}
}
else//iphone
{
UIInterfaceOrientation des=self.interfaceOrientation;
if(des==UIInterfaceOrientationPortrait||des==UIInterfaceOrientationPortraitUpsideDown) //iphone portrait
{
}
else //iphone -landscape
{
}
}
return YES;
}
Which iOS are you building for? It was deprecated in iOS 6.0. (You should override the supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation methods instead.)
Also you can call shouldAutorotate on the UIViewController class:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/shouldAutorotate
Ensure you have checked the Supported Interface Orientations within the "Summery" tab of the project settings (Select the project name in the 'Project Navigator' at the very top).
If you have not selected the orientations you want to use here, then the simulator/iphone will not allow the screen to change orientation.
I had this problem but it worked in iOS6 but not iOS5. Turns out I had a view in my storyboard that I hadn't made a viewcontroller class for yet.
...and last but not least, make sure you haven't activated the setting "Portrait Orientation Locked" on your test device (of course doesn't apply to the simulator), this will disable rotating in any app no matter what shouldAutorotateToInterfaceOrientation returns.
I'd like the app to work like it would be as if I locked the orientation manually. I'm trying to find how I can lock the orientation for an app. In the info.plist, I have this setting:
Supported interface orientations (iPad)
Item 0 Landscape (right home button)
Item 1 Landscape (left home button)
I thought that would be enough to keep my viewControllers from staying in landscape mode and not portrait. But it does not. Do I need to do
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
in ALL my viewControllers? Thanks!
All though implementing shouldAutorotateToInterfaceOrientation in all your view controllers will work, it is probably not the fastest or most practical way of doing what you are trying to accomplish.
If any of your view controllers in your hierarchy do not conform to the orientation change, then iOS will stop trying to rotate them. What this means is that only your root view controller needs to have implemented shouldAutorotateToInterfaceOrientation with only landscape orientations. Each view controller pushed or added will conform to that function.
I have had to do this in several of my apps and it was required for several reasons.
In the end and after a lot of testing, we determined that the condition has to be set on the info.plist AND on every viewController.
So make sure it is set on the plist and that every shouldAutorotateToInterfaceOrientationonly returns yes for the allowed orientation.
This is because the plist will help you with allowed LAUNCH orientations, but your app could still rotate afterwards, specially when using modal views.
You can download one of my free apps that does thins on iPad: http://itunes.apple.com/mx/app/hoteles-city/id471505865?mt=8
Yes you do.
I have a different solution however. In every UIViewController, I use:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft){
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
} else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
} else {
return NO;
}
}
This one has me ripping my hair out. My iPad application is setup as follows:
In my app delegate I have this:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
in my info.plist I have:
Initial Interface Orientation = UIInterfaceOrientationLandscapeLeft
In my first view controller that is loaded from the app delegate I have:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations.
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
In my second view controller I have:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations.
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Finally the views in both nibs are set to landscape in Interface Builder. The application starts in landscape mode and there is a button that when pressed assigns the second view to the first view:
self.view = secondView.view;
the problem is that even though everything is in landscape the new view is always loaded in portrait mode? Please any help on this would be very very appreciated!
This is the bit you want to change. This is what sets the allowed initial orientations. Change it to suit your needs.
It's in the summary tab of the Target's settings.
Or. if you aren't using Xcode 4 yet - you can set the orientations in the Info.plist:
And so you can see all the keys:
I subclassed UITabBarController in order to override shouldAutorotateToInterfaceOrientation: so that I can support landscape mode in certain circumstances. When I run this, the tab bar controller gives me the following message when the overridden method returns NO
The view controller <...0x644f50> returned NO from -shouldAutorotateToInterfaceOrientation: for all interface orientations. It should support at least one orientation.
Any suggestions on how to get ride of the message other than return YES all the time in shouldAutorotateToInterfaceOrientation?
If you return NO, it means that your view controller can't be displayed on any of the 4 orientations.
You should think which orientations you want it to support and use the orientation parameter they give you to accept those orientations.
For example, if I wanted my view controller to support portrait and landscape right, this would be my implementation (This could be reduced to a line, but I'm expanding it for the sake of clarity):
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIDeviceOrientation)orientation{
if(orientation == UIDeviceOrientationPortrait) return YES;
if(orientation == UIDeviceOrientationLandscapeRight) return YES;
return NO;
}
You can use UIInterfaceOrientationIsLandscape() and UIInterfaceOrientationIsPortrait() to handle which specific orientation you want the UIViewController to support.
In my iPad app, I need to run some layout code to set the proper layout depending on the orientation. By default, the layout is configured for the landscape orientation, so in the case that the app starts in portrait mode, I need to take extra action to configure the views properly for display in portrait.
In my -application:didFinishLaunchingWithOptions: method, I check the orientation using [[UIDevice currentDevice] orientation]. The problem here is that it always returns portrait even if the app is starting in landscape. Is there any way around this?
This is expected behavior. Quoth the UIViewController documentation:
Note: At launch time, applications should always set up their interface in a portrait orientation. After the application:didFinishLaunchingWithOptions: method returns, the application uses the view controller rotation mechanism described above to rotate the views to the appropriate orientation prior to showing the window.
In other words, as far as the device is concerned the orientation is portrait while the application is launching. At some point after application:didFinishLaunchingWithOptions: it will detect the different orientation and call your shouldAutorotateToInterfaceOrientation: method and then your other view rotation methods, which you should handle as normal.
This is the best way to check for orientation on launch. First, create a new method in your AppDelegate that checks the orientation:
-(void)checkLaunchOrientation:(id)sender{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL isLandscape = UIDeviceOrientationIsLandscape(self.viewController.interfaceOrientation);
if (UIInterfaceOrientationIsLandscape(orientation) || isLandscape) {
//do stuff here
}
}
At the end of -application:didFinishLaunchingWithOptions: run
[self performSelectorOnMainThread:#selector(checkLaunchOrientation:) withObject:nil waitUntilDone:NO];
Use self.interfaceOrientation in your view controller - it's a property of UIViewController that is set by iOS for you, and in some cases is more reliable than [[UIDevice currentDevice] orientation].
Here's a detailed description: http://bynomial.com/blog/?p=25
As mentioned in a blog post above, there is a set of macros for testing orientation. That blog post however mentions UIDeviceOrientationIsPortrait. I like the following below, it's a minor twist.
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
NSLog(#"Portrait");
}
else
{
NSLog(#"Landscape");
}
An observation I've made is that you can't call this code in a table view, pushed on to a Navigation Controller embedded in the split view controller. So in other words you can't call it from the master view controller. You have to replace the "self.interfaceOrientation" with splitviewcontroller.interfaceOrientation, assuming you maintain a reference to the parent split view controller.
Use the status bar orientation instead to detect it.
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
then perform the if's on the "orientation" you have obtained from above.
So the question is about checking orientation at startup. The answer is sadly "You can't".
But AFTER startup, you can check orientation the normal way (as others have described).
If anyone else comes here looking for an answer, simply stop looking since, at startup the orientation variable is not set (all views frames/bounds also report being in portrait even if they aren't).
You want to make sure you set the proper keys in your Info.plist to allow for the orientations you want:
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
Not that you need another answer, but I thought I should add that you almost never want to use [[UIDevice currentDevice] orientation]. That method returns the orientation of the device, which isn't necessarily the same as the orientation of the interface.
It's not true that you can't figure out the launch orientation, it is true that it's a pain in the rear to do so.
here's what you need to do.
your first UIViewController needs to have some special logic to nab the information you'd like.
you might even want to create a UIStartupController just for these purposes if it's that important to your flow.
in the case of my project, we already had such a startup controller present.
all you need is the following code
-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.launchOrientation = UIDeviceOrientationUnknown;
}
return self;
}
-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
if (self.launchOrientation == UIDeviceOrientationUnknown && duration > 0)
self.launchOrientation = UIInterfaceOrientationPortrait;
else
self.launchOrientation = toInterfaceOrientation;
}
basically, if we're not launching in UIInterfaceOrientationPortrait, the first rotation callback sequence will actually reveal the launch orientation.
if launched in UIInterfaceOrientationPortrait, then we need to check that the first rotation's duration is non zero, and then we know that it was launched from portrait.