ios dev - shouldAutorotateToInterfaceOrientation method not called for portrait mode - iphone

In my rootViewController, I re-implemented the method shouldAutorotateToInterfaceOrientation like this.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
NSLog(#"Orientation - Portrait");
break;
case UIInterfaceOrientationLandscapeLeft:
NSLog(#"Orientation - Left");
break;
case UIInterfaceOrientationLandscapeRight:
NSLog(#"Orientation - Right");
break;
case UIInterfaceOrientationPortraitUpsideDown:
NSLog(#"Orientation - UpsideDown");
break;
default:
break;
}
return YES;
}
When I rotate my device, this method is called for LandscapeRight, LandscapeLeft and UpsideDown, but not for the Portrait orientation.
At the launch the view is in portrait mode, and this method is called with UIInterfaceOrientationPortrait. But when I rotate the device this method is not called only for this orientation.

shouldAutorotateToInterfaceOrientation is normally only called once to tell the caller, what orientations the app will support (an ORed value or YES for all). You might be looking for willRotateToInterfaceOrientation:duration: to check the orientation and/or do some rearrangements before displaying the new orientation.

Related

xcode - How do I keep views locked into portrait mode, but still allow one view to rotate?

I'm having a problem with device rotation. Except for ONE view, where I show a company splash screen, I want to lock all the remaining app views into Portrait display. In the project settings the supported orientations are Portrait and LandscapeLeft. In the 'Company Splash' it works fine and the view rotation is locked into LandscapeLeft no matter how I rotate the device. On all the other views when I rotate the device to the left the view alters instead of staying in portrait display. The methods are not even firing? If I remove Landscape left from the supported Orientations in the project, that screws up the 'Company Splash' view. I tried changing the shouldAutorotate return to NO, but that didn't help. Tried to work my way through the suggestions posted here, but that didn't help. If I put the following code into my AppDelegate.m, everything is locked into portrait mode and the 'Company Splash' crashes when accessed.
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
How do I lock the view into portrait mode no matter how the device is rotated except for the one screen?
** method from the 'Company Splash' view. Again, works like it is supposed to.
-(NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
** methods from all the other views, which rotate out of portrait when I don't want them to
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// IOS5 Only returning that it should rotate to potrait
return (interfaceOrientation == UIDeviceOrientationPortrait);
}
-(BOOL)shouldAutorotate
{
// forcing the rotate IOS6 Only
return YES;
}
-(NSInteger)supportedInterfaceOrientations
{
// return number or enum IOS6 Only
return UIInterfaceOrientationMaskPortrait;
}
I thought maybe it might be because a UITabBarController is the root controller and I'm in a ViewController off of that? The methods are not even firing?
Add an observer to the viewDidLoad method of the view you want to rotate like this :
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
and then set the views according the the landscape view inside the orientationChanged method like this :
- (void) orientationChanged:(NSNotification *)note{
UIDevice * device = [UIDevice currentDevice];
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
break;
case UIDeviceOrientationPortraitUpsideDown:
break;
case UIDeviceOrientationLandscapeLeft:
break;
case UIDeviceOrientationLandscapeRight:
break;
default:
break;
};
}
Slap this method into the view controller you want locked in a certain orientation.
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
just change to the orientation you want (the above locks it in landscape)
maybe u should allow all orientations, and lock portrait orientation in each class except company splash with
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
} else {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
}

iPad Interface Orientation Problem

When user tap on the UIView (which is fullscreen) my app needs to detect orientation and do some stuff. But there is one tiny problem.
If I start application in landscape mode and user tap background 'interfaceOrientation' variable is '0' and I don't know how to rearrange view elements. If I rotate simulator once everything is fine but if not 'interfaceOrientation' is '0'. What to do here?
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
...
}
else if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
...
}
else if(interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
...
}
I'm not sure how well that is solvable. UIDeviceOrientationUnknown is 0. This means, especially for the iPad which hasn't got a gyroscope, that the orientation at this time is simply not know. Imagine your iPad laying on a table, flat and the user is starting your application: there isn't any means to define that your application is actually running in landscape or portrait, unless you tilt the device accordingly. Hence.. the orientation at startup is always 0 (unknown).
You are casting a UIDeviceOrientation type to a UIInterfaceOrientation type. Device orientations have several different values beyond those of an interface orientation.
Try using:
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
switch (deviceOrientation) {
default:
case UIDeviceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
case UIDeviceOrientationUnknown:
//...
break;
case UIDeviceOrientationLandscapeLeft:
//...
break;
case UIDeviceOrientationLandscapeRight:
//...
break;
}
Edit: If the device orientation is unknown you should just set up your regular portrait view.
You should be able to access [UIApplication sharedApplication].statusBarOrientation if you can't access self.interfaceOrientation from your view controller.
Also, sometimes calling self.interfaceOrientation in viewDidLoad is risky because the view will load before it is aware of its orientation, so it will perform the rotation afterwards. In that case try finding it in viewWillAppear.
Or just override willRotateToInterfaceOrientation:duration and pass that information to the UIView that needs it. Note: that won't get called if you have a xib set to that orientation.

UIActionSheet orientation

I am having a problem trying to get the orientation of the device correct. I have to show an action sheet that should come depending on the orientation of the device. Here is the code I am using.
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
switch (orientation)
{
case UIDeviceOrientationPortrait:
case UIDeviceOrientationFaceUp:
case UIDeviceOrientationFaceDown:
case UIDeviceOrientationUnknown:
case UIDeviceOrientationPortraitUpsideDown:
[self displayActionSheetInPotraitMode];
break;
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
[self displayActionSheetInLandscapeMode];
break;
default:
[self displayActionSheetInPotraitMode];
break;
}
Let's look what the UIDevice Class Reference tells us about the orientation property.
The value of this property always returns 0 unless orientation notifications have been enabled by calling beginGeneratingDeviceOrientationNotifications.
So, you should call
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]
somewhere earlier in your code.
Also, I'd like to suggest a way to simplify your current code:
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(orientation)) {
[self displayActionSheetInLandscapeMode];
} else {
[self displayActionSheetInPotraitMode];
}
See the answer here: UIActionSheet orientation
You should add a UIView (add it as subview to UIWindow) -> transform it to proper orientation and then add the UIActionSheet to this UIView.

iPhone, duplicate method message after hardware rotate?

I am pretty sure what I am seeing is how this is supposed to work, but I as just curious as to why. When I rotate the iPhone in the simulator the method (see below) that allows the orientation gets called twice with each single rotation. Is there a reason for this?
-(BOOL)shouldAutorotateToInterfaceOrientation:interfaceOrientation
EDIT_001
This is what gets called when the iPhone detects a rotation, I am just curious that each time I do a rotate in the simulator the NSLog statements print twice (i.e. the method is getting called twice)
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
BOOL autoRotate = NO;
switch(interfaceOrientation) {
case UIInterfaceOrientationPortrait:
NSLog(#"Orientation(%d): Portrait Supported", interfaceOrientation);
autoRotate = YES;
break;
case UIInterfaceOrientationPortraitUpsideDown:
NSLog(#"Orientation(%d): UpsideDown unsupported", interfaceOrientation);
autoRotate = NO;
break;
case UIInterfaceOrientationLandscapeLeft:
NSLog(#"Device: RIGHT, Interface: LEFT(%d)", interfaceOrientation);
autoRotate = YES;
break;
case UIInterfaceOrientationLandscapeRight:
NSLog(#"Device: LEFT, Interface: RIGHT(%d)", interfaceOrientation);
autoRotate = YES;
break;
}
return(autoRotate);
}
gary
Have you checked the arguments passed in to shouldAutorotateToInterfaceOrientation:? I have found it gets called one for horizontal, and once for vertical - basically to ask which orientations are OK, and then it's usually not called again.
If you are doing something in there you want done every time the device is rotated, I think it's a lot better to either use willRotateToInterfaceOrientation:duration: or listen for the rotation notifications (via UIDeviceOrientationDidChangeNotification), and leave shouldAutorotateToInterfaceOrientation: to flag what your app allows for rotation of that view controller.
This happens when the view is inside a tab controller, because the tab controller also calls that same method. Hope that helps.
-Oscar

Changing modal UIView's orientation to landscape mode on iPhone

Im having a modal view displayed on top of tab bar controller the orientation of tab bar controller and my modal view is currently in portrait mode, i need to only change my modal views orientation to landscape mode,
i Tried usign UIDevice Orientation but no success it only works when .plist has UIDeviceOrientationKey, and i dont want whole of my application in landscape mode. secondly i even tried using UIApplication setStatusBarOrientation but my view doesn't respond to it i.e. only my device(simulator) get rotated but the view still remains in portrait mode, using affine transformation on UIView creates an empty view my view is created through XIB.
Please Help
Thanks Rakesh
I have used this and it works well with some tweaking.
Until today I used the following solution:
-(void)setOrientation:(UIInterfaceOrientation)orientation
{
SEL rotation = #selector(_setRotatableViewOrientation:duration:);
NSMethodSignature * methodSignature = [window methodSignatureForSelector:rotation];
if (methodSignature)
{
NSInvocation * ivc = [NSInvocation invocationWithMethodSignature:methodSignature];
[ivc setTarget:window];
[ivc setSelector:rotation];
// arg0 will be self, 1 will be cmd_ (current method selector)
[ivc setArgument:&orientation atIndex:2];
double duration = 0.4;
[ivc setArgument:&duration atIndex:3];
[ivc invoke];
}
}
-(void)normalizeOrientation
{
UIDeviceOrientation dOrientation = [UIDevice currentDevice].orientation;
int orientation = -1;
switch(dOrientation)
{
case UIDeviceOrientationPortrait:
orientation = UIInterfaceOrientationPortrait;
break;
case UIDeviceOrientationPortraitUpsideDown:
orientation = UIInterfaceOrientationPortraitUpsideDown;
break;
case UIDeviceOrientationLandscapeRight:
orientation = UIInterfaceOrientationLandscapeLeft;
break;
case UIDeviceOrientationLandscapeLeft:
orientation = UIInterfaceOrientationLandscapeRight;
break;
}
if (orientation != -1 && orientation != tabBarController.interfaceOrientation)
[self setOrientation:orientation];
}
but the official AppStore wont accept new releases of my App due to
_setRotatableViewOrientation:duration:transition:toView:
isn't documented API.
So be aware for use it in your commercial projects!
Apple new automated API checker will reject your App!