32

I believe this is a common issue and many answers don't work anymore, many just partial, if you are under iOS7 and your iPad app is Landscape only, but you want to use the UIImagePickerController with source UIImagePickerControllerSourceTypePhotoLibrary or UIImagePickerControllerSourceTypeCamera.

How to set it right, so it's working 100%? And you don't get mixed orientations and avoid the error "Supported orientations has no common orientation with the application, and shouldAutorotate returns YES".

krsteeve
  • 1,794
  • 4
  • 19
  • 29
Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179

6 Answers6

83

If your iPad app is landscape only in all conditions, just do these 3 steps :

1) In your app delegate

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return UIInterfaceOrientationMaskAll;
}

2) Create a category header

#import "UIViewController+OrientationFix.h"

@implementation UIViewController (OrientationFix)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

@end

3) Create a category implementation

#import "UIImagePickerController+OrientationFix.h"

@implementation UIImagePickerController (OrientationFix)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

@end

Note: You don't need to import these categories anywhere, just enough they are compiled with the project

Note: no need to implement these methods in any VC

Note: no need to change your plist supported orientations

This is tested and working under any conditions

Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179
41

I have seen this code from Apple's Sample Code.

UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;

Due to this UIModalPresentationCurrentContext UIImagePickerController will be opened as per device's current orientation.

Mihir Oza
  • 2,768
  • 3
  • 35
  • 61
  • 3
    This is the best answer. Using categories is a hack. This works with photo, video and library source type. Tested with iOS8.3. – Florian L. May 12 '15 at 11:51
  • 1
    This answer is more beautiful than any that I've seen. – Rstew Jul 15 '15 at 22:31
  • 3
    iOS 8.4: Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and [PUUIAlbumListViewController shouldAutorotate] is returning YES' – elsurudo Jul 24 '15 at 07:59
  • 1
    Work like charm on iOS 8.4. – Chinthaka Jul 28 '15 at 03:29
  • 1
    Works on iOS 8.4.1. We should vote more her and ask this to be marked as the correct answer. – Totoro Sep 10 '15 at 21:23
  • IOS 9 Works! This is the correct answer. Also for Swift code: imagePicker.modalPresentationStyle = UIModalPresentationStyle.CurrentContext – Rob van den Berg Sep 26 '15 at 12:13
  • 1
    Elsurudo, please note that you still need to tick Device Orientation Portrait to prevent the crash. – Rob van den Berg Sep 26 '15 at 12:21
  • This didn't work for me. But imagePicker.modalPresentationStyle = UIModalPresentationOverFullScreen; did. – l-l Feb 26 '16 at 15:16
  • This didn't work for me either on iOS 9.2 — it doesn't avoid the crash if unless you tick Portrait in your app's orientation settings. – fatuhoku Mar 18 '16 at 09:21
  • It can present vc on iPad pro.But the displayed exception. – frank Sep 26 '16 at 06:17
  • imagePickerController.modalPresentationStyle = .currentContext ... worked perfect for me in iOS10.3 & Swift3.0 – crosscode Jun 18 '17 at 08:57
1

Apple's documentation says:

"Important: The UIImagePickerController class supports portrait mode only."

Although, it works fine in landscape for full screen and on iOS 6.

UIImagePickerController class reference

Collin
  • 6,720
  • 4
  • 26
  • 29
0

Thanks to Peter Lapisu suggestion above. It doesn't work for me (maybe i'm on iOS 8.3) but i was able to modified it to fixed my orientation issues. My codes are below

In app delegate

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskAll;
}

UIImagePickerController category

@implement UIImagePickerController (extensions)
- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [[UIApplication sharedApplication] statusBarOrientation];
}

@end

UIViewController category

@implementation UIViewController (extensions)

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

@end
Tien Dinh
  • 1,037
  • 7
  • 12
0

Although most answers recommend using .currentContext, I have found out after dismissing the imagepicker, everything was wrong.

On an Landscaped iPad, imho it's best if you would use .formSheet:

let picker = UIImagePickerController()
picker.modalPresentationStyle = .formSheet
picker.sourceType = .photoLibrary
picker.delegate = self
self.present(picker, animated: true)
dOM
  • 555
  • 5
  • 14
0

Swift 4 solution

Make sure that when you are having the ViewController embedded in a NavigationViewController to have the fix there. It won't work adding this restriction to the ViewController then...

import UIKit

class MainNavigationViewController: UINavigationController {

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscape
    }
}

And of course the code mentioned above for the AppDelegate:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return .all
}

Btw this is only necessary for iOS 10 and below. Apple seems to have fixed it from iOS 11 and above...

simon
  • 41
  • 1
  • 4