Keyboard appears in wrong orientation in ios - ios

I have one viewcontroller in application that supports landscape and portrait orientations.
On a button click, a popup appears where I should enter the name. everything works as it should on portrait mode.
But if I dismiss the keyboard, rotate the device left or right and then open the popup, keyboard still opens in portrait mode.
I've shouldAutorotate returning true and supportedInterfaceOrientations returning AllButUpsideDown in viewcontroller, so rotation happens automatically.
I tried this and this options but none of them work.
Any ideas what to do?

I got exactly the same wrong keyboard orientation in some of my view controllers recently after I dropped support for iOS 8 and bumped up the deployment target to iOS 9. It turns out that one of my former colleagues used a solution here to solve an old problem when the base SDK was iOS 9 (we're now in 10, and 11 when coding from Xcode 9 beta). That solution (basically override UIAlertController's supportedInterfaceOrientations to only allow portrait) would force present the keyboard in portrait with newer SDK + deployment target even though the app window and the alert itself are in landscape.
Removing that override solved the problem and I don't see any issue with alert over alert.

Try by adding below code to your viewcontroller's viewDidAppear method
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[UIDevice currentDevice] setValue:#(UIDeviceOrientationLandscapeLeft) forKey:#"orientation"];
[[UIDevice currentDevice] setValue:#(self.interfaceOrientation) forKey:#"orientation"];
}

Ok, fixed it, my fault I guess.
It seems Keyboard and UIViewController call supportedInterfaceOrientations separately and rotate based on its return value. I had an if-else statement in there and was returning AllButUpsideDown only in some cases. When keyboard checked whether it was supposed to rotate method returned Portrait, and for viewcontroller value was AllButUpsideDown.
So I changed this:
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
if (someStatement)
{
return UIInterfaceOrientationMask.AllButUpsideDown;
}
return UIInterfaceOrientationMask.Portrait;
}
To this:
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
return UIInterfaceOrientationMask.AllButUpsideDown;
}
And now only ShouldAutoRotate decides whether it rotation should happen or not.
To some up it should look like this:
public override bool ShouldAutorotate()
{
if (someStatement)
{
return true;
}
return false;
}
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
return UIInterfaceOrientationMask.AllButUpsideDown;
}

Create subclass of UIAlertController
MyAlertController.h //header file
#interface MyAlertController : UIAlertController
#end
MyAlertController.m
#implementation MyAlertController
- (BOOL)shouldAutorotate
{
return NO;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
[super supportedInterfaceOrientations];
return UIInterfaceOrientationMaskLandscape;
}
#end

Related

Storyboard ignores UIInterfaceOrientation settings

I have a strange problem with UIInterfaceOrientation. In my project there are many different views, some of them should rotate in landscape mode, and some of them should not. The problem is that all the view which were not created using Storyboard and in which only the UIInterfaceOrientation portrait is enabled this works fine and the view does not rotate, instead all the views created using the Storyboard, even if the UIInterfaceOrientation landscape mode was disabled they keep rotating. In my Xcode project setting those checks are enabled and I cannot change them:
How can I completely disable the device rotation in all the different views? [Storyboard or not].
This is the code I use to disable the device orientation in all the storyboard view controller, but it does not work:
- (BOOL)shouldAutorotate {
return NO;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Try this code maybe it will work for you.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientationMask)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationMaskPortrait);
}
The solution was to assign a UINavigationController class to the UINavigationController in the Storyboard file and to place this code in his .m file:
- (BOOL)shouldAutorotate {
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
Please, check if in your project .plist there are more than one item for orientation or something strange. I sometimes have found that orientation has different values in plist or duplicated keys.
Hope it helps

Universal app supporting portrait and Portrait upside down, but rotation not happening on iPhone - UPDATED

My app is a universal application that supports portrait and portrait upside down orientations.
My app uses a UITabBarController that has UINavigationControllers for 3 UITabBarItems.
To support of of these, i have done the following things:
1) added "supported Interface Orientations" key accordingly for both devices
2) added the following code in app delegate and all other view controllers
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
Everything is going as expected in iPad, but on iPhone, only some of my views (not all) do not respond to change in Orientation..!! Why is this happening??
You should check that all of your view controllers have the rotation defined, and then you should add this to them:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
If you're using a navigation controller, you should create a subclass .i.e. "MyNavController" with the instructions to rotate in its implementation:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
and then use it:
MyNavController *navo = [[MyNavController alloc] initWithRootViewController:myRootController];
As far as I know upside down in portrait mode for the IPhone is not allowed, cause when a user receives a phonecall, the app is on hold and he has the phone upside down. Thats why apple does not want that.

Handling iDevice rotation on iOS 6

I'm having trouble figuring out how to handle device rotation on iOS 6. I have three things that need to change separately when the device is rotated.
I have a parent UIViewController that handles multiple sub UIViewControllers or UINavigationControllers (Its basically a custom UITabBarController). I do not want this to rotate.
Each of these sub view controllers, will either rotate or not rotate depending on its own settings. (I want some to rotate and some to not).
In the tab bar, I want each tab icon (a UIView) to rotate to the orientation.
How would I go about making this happen in iOS 6, I got everything working in iOS 5.
Here is what I have so far:
In the parent UIViewController:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (BOOL)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
In the sub view controllers:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (BOOL)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
There's a bit more to this to support iOS6 correctly. The iOS 6 Release Notes sketch things out:
https://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html
This bit might be useful:
For compatibility, view controllers that still implement the shouldAutorotateToInterfaceOrientation: method do not get the new autorotation behaviors. (In other words, they do not fall back to using the app, app delegate, or Info.plist file to determine the supported orientations.) Instead, the shouldAutorotateToInterfaceOrientation: method is used to synthesize the information that would be returned by the supportedInterfaceOrientations method.
But you should also take a look at Session 236 from WWDC 2012 - The Evolution of View Controllers.
If you want to support different orientation in navigation stack, you must subclass UINavigationController first and override supportedInterfaceOrientations.
- (NSUInteger)supportedInterfaceOrientations
{
//I want to support portrait in ABCView at iPhone only.
//and support all orientation in other views and iPad.
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
// find specific view which you want to control.
if ([[self.viewControllers lastObject] isKindOfClass:[ABCView class]])
{
return UIInterfaceOrientationMaskPortrait;
}
}
//support all
return UIInterfaceOrientationMaskAll;
}

iOS 6 autorotation in simulator varies from actual iOS 6 device

My app will not autorotate in the iOS 6 GM simulator but it does with the same version of iOS on the device. Could this be a simulator bug? The app is using deprecated autorotation methods, but they are working fine on the device itself which makes me wonder if the simulator APIs are different?
It should still work with the deprecated rotate methods, but you need to add the following to your didFinishLaunchingWithOptions: method:
self.window.rootViewController = yourRootViewController;
This tells the main window what view controller to send the rotate notifications to. This is new with the iOS 6.0 SDK.
This is what I added to get my app working again:
// Tell the system what we support
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
// Tell the system It should autorotate
- (BOOL) shouldAutorotate {
return YES;
}
// Tell the system which initial orientation we want to have
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
Adding the following was not enough to make it work on the simulator:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (BOOL) shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
To make it work, I also added the following inside the didFinishLaunchingWithOptions function of the appDelegate class:
self.window.rootViewController = viewController;
I stopped getting the following error after this addition:
Application windows are expected to have a root view controller at the end of application launch
- (BOOL)shouldAutorotate {
return NO;
}
and set the supported rotations for the root view controller in the app plist file to only portrait.

Can you disable rotation globally in an iOS app?

I have an app made up of a lot of view controllers... in the project summary I've set Portrait orientation as the only supported device orientation.
However, the app still gets messed up when turned sideways.
My question is, is there a way to globally disable autorotation through app delegate or something?
Or do I have to go into all of my view controllers and add the "shouldAutorotateToInterfaceOrientation" method?
Just don't want to miss adding it to one or something...
Thanks!
In Info.plist expand "Supported interface orientations" and remove Landscape items to make your application only run in portrait mode.
There are three kinds of Device orientation keys there in the info.plist now.
Supported interface orientations (iPad)
Supported interface orientations (iPhone)
Supported interface orientations
Third one is I think for non-universal apps and rest two above are for iPad and iPhone.
You should give them a try.
After struggling to set in UIViewController's shouldAutorotate and supportedInterfaceOrientation methods, with no success in iOS6, I found the most effective is to set it in app delegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
However returning UIInterfaceOrientationMaskPortraitUpsideDown was crashing my app. I dont know whats wrong I was doing!
in root view controller's method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
set 'return NO';
this should do for all the Views.
If you're supporting iPad, then you SHOULD NOT uncheck the landscape orientations, as it will prevent your app from being accepted by Apple on App Store.
To prevent rotating before the app shows your first screen, put this inside your AppDelegate.m
This method works and tested in iOS 7.1 above.
// G - fix for ipad.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
Haris Hussain's answer appears to be deprecated now, as of IOS 6, but there are new methods available for limiting/enabling rotation.
Here are the methods listed in the UIViewController header:
// New Autorotation support.
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);
// Returns interface orientation masks.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);
Note that shouldAutoRotate doesn't seem to work if you start the app in an already rotated state!
Swift
iOS 6+
The recommended way is to override shouldAutorotate in every attached view controller. If you override this property in the root view controller, then all "attached" view controllers will also inherit the behavior. Presented view controllers, however, can become "unattached" to the root and thus would not inherit the override and so you would need to override the property in those view controllers separately.
class RootViewController: UIViewController {
override var shouldAutorotate: Bool { false }
}
class PresentedViewController: UIViewController {
override var shouldAutorotate: Bool { false }
}
However, if you simply subclass UIViewController and only use the subclassed view controllers in your project then you have a truly global fix (using code).
class NonrotatableViewController: UIViewController {
override var shouldAutorotate: Bool { false }
}
Settings alternative (no code)
Perhaps the most global fix is editing the Info.plist file in the info tab in the target's settings. There is a supported-interface-orientations key with each value representing a supported orientation. Deleting all but portrait will disable rotation in all view controllers, attached or unattached to the root.

Resources