I'm attempting to set a view's orientation based on if the device is running on an iPhone or an iPad. I have a supportedInterfaceOrientations method, which I call from viewDidLoad:
[self supportedInterfaceOrientations];
In the supportedInterfaceOrientations method, I check if the device is an iPhone. If it is, the view should only be set to a portrait orientation. Otherwise, all orientations should be supported:
- (NSUInteger)supportedInterfaceOrientations
{
//If the device is an iPhone, we're going to make this page portrait-only
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
return UIInterfaceOrientationMaskPortrait;
}
//If it's an iPad, we'll support all orientations.
else {
return UIInterfaceOrientationMaskAll;
}
}
However, when I run the app on an iPhone, the view does not stay locked in portrait mode, but will rotate based based on the phone's orientation. Does anyone have an idea of what I'm doing wrong? Thank you!
EDIT I forgot to mention that this particular view is part of a Navigation Controller, which I just realized is probably the cause of the problem.
EDIT2 The xib for this particular view is also set to 'portrait' in the 'Simulated Metrics' section. Additionally, below is the code where I build the view controller and present the view:
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
self.navigationController.delegate = self;
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
Use:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
//If the device is an iPhone, we're going to make this page portrait-only
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
return UIInterfaceOrientationMaskPortrait;
}
//If it's an iPad, we'll support all orientations.
else {
return UIInterfaceOrientationMaskAll;
}
}
Related
I am using UIImagePickerController to select a single image from photo library. There is a strange issue on iPad when it is in landscape mode.
The image picker is presented using UIPopoverPresentationController on iPad as recommended. When it is first presented, the status bar is correct:
However, when going into the second level of the photo library, the status bar is changed to portrait mode:
What I have noticed so far are:
This issue only appears in iOS 11, not iOS 10.
When it happens, rotate the iPad to portrait and back to landscape will fix the status bar orientation.
It only happened the first time presenting the picker controller.
If ignore, presenting other modal view will be in portrait mode:
The code that presenting the uiimagepickerController is as follow:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.modalPresentationStyle = UIModalPresentationPopover;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
[self presentViewController:picker animated:YES completion:nil];
UIPopoverPresentationController *popupController = picker.popoverPresentationController;
if (popupController) {
popupController.barButtonItem = sender;
}
Any idea what have I done wrong, or it is a bug?
Whole example project can be downloaded here:
https://www.dropbox.com/s/zgipclyr0mz26c6/test.zip?dl=0
I have finally found the cause of my issue.
My app needs to support all orientation on iPad and Portrait mode only on iPhone. Therefore I added the following code of UIApplicationDelegate:
- (UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (window.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
But sometimes it gives me nil window, as in the case of UIImagePickerController presented using UIPopoverPresentationController on iPad, and will return UIInterfaceOrientationMaskPortrait and cause the status bar rotates to portrait mode. I have also noticed that this happens only when UIRequiresFullScreen is checked.
I have solved my issue by checking that window is not nil as below:
- (UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (window) {
if (window.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
} else {
return UIInterfaceOrientationMaskAll;
}
}
I have a universal application that supports both iPad and iPhone. On the iPad I support all orientations and on the iPhone, only Portrait.
I want one view controller (which is displayed modally), when running on the iPhone, to be displayed in any orientation that the device is in. I have seen many tutorials and SO posts that suggest using the -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window app delegate method and this seems to work absolutely fine in respect to rotating the modal view controller. However, when I dismiss the modal view whilst in landscape, the entire app remains landscape.
Ideally, as soon as the modal view is dismissed the app should go back into portrait mode.
After investigation, it appears that the -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window callback is not called after dismissing the view controller and I can't figure out why.
I have had a play with the example app here, and the callback is fired when dismissing the view controller, which I can't figure out as to why. The only difference I can see is that my view hierarchy is a lot more complex and that I'm displaying a Navigation Controller rather than an explicit view controller but I don't see how that should affect the callback.
Any ideas as to finding a solution to this?
Thanks
You can try to use this method (working in app store build):
[[UIDevice currentDevice] performSelector:#selector(setOrientation:)
withObject:(__bridge id)((void*)UIInterfaceOrientationPortrait)];
In appdelegate:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
// Get topmost/visible view controller
UIViewController *currentViewController = [self topViewController];
//Hire check your needed device ore other things you need
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )
{
//device is iphone
if ([currentViewController respondsToSelector:#selector(canRotate)])
{
// Unlock landscape view orientations for this view controller
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
else
//device Ipad
return UIInterfaceOrientationMaskAll;
}
}
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
in the needed view to rotate make sure to implement
- (void)canRotate { }
This will allow you to rotate only the view you want for iPhone device.
I got this code with the help of an old stackoverflow post but i can`t find the link to it now
I have a project for the iPad that I've made using iOS7 which displays at one point a view controller in landscape mode. On this view controller, there is a UITextField which is the first responder on the screen, and thus immediately when the user comes to this screen, the keyboard is supposed to be presented, which it does.
The problem however, is that the keyboard is being displayed in portrait mode, when the view controller is being displayed in landscape mode, in iOS 8. How do I correct this, so that the orientation of the keyboard is consistent with the view controller (which is still being displayed in landscape mode, correctly)? Just for the record, this view in particular is using a .xib file, and not in storyboard.
Below is the code that I have:
MyLandscapeViewController.m
relevant methods:
-(BOOL)shouldAutorotate {
return NO;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;
}
- (void)viewDidUnload {
[self setKeyboardButton:nil];
[super viewDidUnload];
}
For the view controller, I created a custom navigation controller:
MyNavigationController.m
-(BOOL)shouldAutorotate{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
From my application, it is called as follows:
MyLandscapeViewController *myView = [[MyLandscapeViewController alloc] initWithNibName:#"MyLandscapeViewController" bundle:nil];
MyNavigationController *navigationController = [[MyNavigationController alloc] initWithRootViewController:myView];
[self.rootViewController presentViewController:navigationController animated:YES completion:nil];
What changes do I need to make for this to work on iOS 8?
Try this.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationLandscapeLeft] forKey:#"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
My application is working fine for iOS5. But for iOS6 I am getting the following orientation problem.
I have a ViewController VC1. when you rotate (change the orientation to UIInterfaceOrientationLandscapeRight) I want to present another ViewController VC2 and when you rotate back I need to dismiss VC2 and the VC1 should be in Portrait mode.
I am using tabBar in my application and I want this feature only for the first tab.
In tabBar I have written
-(BOOL) shouldAutorotate
{
UINavigationController *nav = (UINavigationController *)self.selectedViewController;
if ([nav.topViewController isKindOfClass:[MainViewController class]])
{
return YES;
}
else
{
return NO;
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//Here I am writing code for presenting view(using notifications)
// but When I rotate the device to landscape it's getting called but when I rotate back
//to portrait I not getting called.
}
Thank you.
Please try this with ios 6 :(Example)
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
I know that there are lots of threads about how to force an orientation in IOS6 but none of them seems to work for me so now I need some help figuring this out.
I have a navigation based app that has many view controllers. All of them are in portrait view exept one that has to load in landscape mode (without having the user turning the phone first).
In the implementation of my navigation controller, I have added shouldAutorotate, supportedInterfaceOrientations and preferredInterfaceOriantationForPresentation.
#implementation UINavigationController (Rotation_IOS6)
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
#end
So it returns the values that have then defined in each view controller.
In the app delegate I have the supportedInterfaceOrientationsForWindow.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
//Default orientations value
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
//Get orientation from the last view controller
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
In each view controller I then have my settings for that view, for example:
// Only allow portrait view
-(NSInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return YES;
}
And I push the next view controller like this:
NextViewController *nxtController = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[self.navigationController pushViewController:nxtController animated:YES];
But when I push the landscape view controller, while holding the phone in portrait orientation, It also loads in portrait mode. If I then tilt the phone it triggers the autorotate function and rotates the view into landscape mode, and then it is locked in that mode. However I need to lock it in landscape mode without using the phones orientation to trigger it to check autorotate.
Any ideas?
You could try to force the viewController to show in landscape by using the shouldaAutorotateToInterfaceOrientation that always return landscape, such as:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
go to project settings and remove the selection on the modes you do not want.