I am trying to open a UIImagePickerController object in my application using this code:
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imgPicker.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:self.imgPicker animated:YES completion:nil];
But then the application crashes and displays the following error:
Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason:
'preferredInterfaceOrientationForPresentation must return a supported interface orientation!'
I also added following methods in my ViewController class
- (BOOL) shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationMaskPortrait;
}
So, what else should I do to present this UIImagePickerController?
This seems to be because the choose-photo VC doesn't implement the new orientation methods. To fix this, make sure for root view controller does implement them, even when the top VC doesn't.
In code:
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate {
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations {
UIInterfaceOrientationMask topControllerOrientationMask = [self.topViewController supportedInterfaceOrientations];
return topControllerOrientationMask ? topControllerOrientationMask : UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
UIInterfaceOrientation topControllerOrientation = [self.topViewController preferredInterfaceOrientationForPresentation];
return topControllerOrientation ? topControllerOrientation : UIInterfaceOrientationPortrait;
}
#end
About the crash problem you can read Here
Also shouldAutorotateToInterfaceOrientation must return not UIInterfaceOrientationMaskPortrait, but UIInterfaceOrientationPortrait,
about the difference you can read Here
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationPortrait;
}
I think your trying to launch image picker your app on iPad. If it is so, you cannot launch picker this type on iPad, it works only on iPhone. For using ImagePicker on iPad, launch imagePicker using UIPopOver.
I have same problem few days ago. I found this following trick.
Put this code in your
AppDelegate.m
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
And also put this code in your UIImagePickerViewController class.
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
Because in iOS-6 UIImagePickerController must be follow portrait orientation.
Related
I used this code to block the rotation before ios 7 (i was also using xibs, now storyboard)
- (BOOL)shouldAutorotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationPortrait;
}
now that i migrated to storyboard and ios7 it is not working, my view is still rotating.
UPDATE:
I solved this by adding this code to the delegate, now my previous code works like charm
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.fullScreenVideoIsPlaying) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
Atrik's code worked. Here is a more complete solution which allows locking and unlocking of portrait-mode-only even with the use of UINavigationController
appdelegate .h
#property (nonatomic) BOOL screenIsPortraitOnly;
appdelegate .m
#pragma mark - View Orientation
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.screenIsPortraitOnly) {
return UIInterfaceOrientationMaskPortrait;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
}
For all view controllers where I need Portrait Lock
If you haven't used a subclass which has the app delegate imported then don't forget to import the delegate. For most view controllers I use a subclass of UIViewController which at least does importation.
#import "AppDelegate.h"
I use this for all portrait locked viewcontrollers.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:true];
[self portraitLock];
}
-(void) portraitLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = true;
}
#pragma mark - interface posiiton
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL) shouldAutorotate {
return NO;
}
ViewDidLoad runs before viewDidAppear so I run this in my subclass of UIViewController to unlock all screens. The viewWillAppear with the lock method is used only in the cotrollers which I need to lock the screen.
- (void)viewDidLoad
{
[super viewDidLoad];
[self portraitUnLock];
}
-(void) portraitUnLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = false;
}
If you only want in landscape mode then you can do it with xcode project setting
go to Target > summary > support interface orientations
Or you can do a code
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
In XCode 5, which is required to be used for iOS7 development, you can go to your target and under Deployment Info uncheck everything except Portrait for device orientation.
If you don't want your app to rotate at all (no matter which view is active), you can click on your project in the Xcode sidebar, scroll down, and deselect Landscape Left and Landscape Right.
Autorotation is not working in ios6.1. But following code is working in other app.
code:
#implementation UINavigationController (RotationIn_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
#end
- (BOOL)shouldAutorotate
{
//returns true if want to allow orientation change
return TRUE;
}
- (NSUInteger)supportedInterfaceOrientations
{
//decide number of origination tob supported by Viewcontroller.
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
//from here you Should try to Preferred orientation for ViewController
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationPortrait;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval)duration
{
}
ios6 uses mainly the plist options for autorotation. Try to setup the supported orientations fields.
Have you tried to modify the plist?
Please check your project targets summery is like below
I have a view controller that contains an image and a tableview. From this view controller I connected a segue to a landscape view that contains the image in full screen (same idea used when you turn sideways the Stocks app from Apple to see the graph in full screen).
This segue is called by the following method:
- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
[self performSegueWithIdentifier: #"toGraph" sender: self];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissViewControllerAnimated:YES completion:nil];
isShowingLandscapeView = NO;
}
}
Besides this, when the iphone is at portrait orientation, I can also drill-down the tableview a couple more levels. The problem is the following: at those consequent levels, the segue to the landscape view still gets triggered when I turn the orientation to landscape!... what can I do so that this does not happen? I am only interested in going to landscape mode from the first view which contains the image.
Thank You in advance!
I don't know for sure if I got your issue right.. but if you mean with "drill-down the table view" to go deeper in a navigation controller hierachy, you can try the following..
That's what I did in a (I think) similar situation:
AppDelegate:
in .h:
#property (nonatomic) BOOL shouldAutorotate;
in .m:
// in didFinishLaunchingWithOptions:
self.shouldAutorotate = NO;
// still in .m file
// Autorotation handling
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return self.shouldAutorotate ?
UIInterfaceOrientationMaskAllButUpsideDown :
UIInterfaceOrientationMaskPortrait;
}
Navigation Controller presenting Portrait Controller
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSUInteger)supportedInterfaceOrientations
{
if (self.selectedViewController)
return [self.selectedViewController supportedInterfaceOrientations];
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate
{
return YES;
}
Portrait View Controller (here's also a very similar segue handling that you have):
in viewWillAppear:
[(AppDelegate *)[[UIApplication sharedApplication] delegate] setShouldAutorotate:YES];
rotation handling:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Landscape View Controller (probably your full screen image):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Deeper in the navigation controller hierachy (where only portrait is wanted):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Looks somehow complicated, but that was the only way, I managed to get those rotation things working properly in both iOS5 and 6.
I'm a little bit confused.
I want my app to rotate in exactly one of my 5 Viewcontrollers.
I created a Category for UINavigationcontroller implementing the necessary methods for rotating in ios 6.
#import "UINavigationController+IOS6Rotation.h"
#implementation UINavigationController (IOS6Rotation)
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if (INTERFACE_IS_PAD) {
return UIInterfaceOrientationLandscapeLeft;
}
else{
return UIInterfaceOrientationPortrait;
}
}
#end
I also have implemented these methods in all my ViewControllers which should not rotate.
- (BOOL)shouldAutorotate {
return NO;
}
- (BOOL)supportedInterfaceOrientations {
if (INTERFACE_IS_PAD) {
return UIInterfaceOrientationMaskLandscape;
}
else{
return UIInterfaceOrientationMaskPortrait;
}
}
The one who should rotate returns YES in shouldAutorotate
On Startup, i use an extra Viewcontroller to show a Splashscreen. This SplashScreen is displayed as RootViewController like this.
vc_splash = [[SplashScreenViewController alloc] initWithNibName:#"SplashScreenViewController" bundle:[NSBundle mainBundle]];
[self.window setRootViewController:vc_splash];
DefaultSHKConfigurator *configurator = [[MySHKConfigurator alloc] init];
[SHKConfiguration sharedInstanceWithConfigurator:configurator];
[self.window makeKeyAndVisible];
When I'm finished loading my database, the splashscreen is exchanged for the mainscreen.
self.viewController = [[MainViewController alloc] initWithNibName:#"MainViewController_iPhone" bundle:nil];
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController: self.viewController];
[self.window setRootViewController: navControl];
Problem now is, that only my Splashscreen calls shouldAutorotate, but the other screens don't.
Can someone tell me if i have missed some essentials here?
I thought i had done all necessary stuff to get that bl****y autorotation to work correctly in ios 6...
Thx in advance,
Maverick1st
**update**
If you want your iPad to start in Landscape, be sure to return YES in your shouldAutoRotate,
this is working for me add supportedInterfaceOrientationsForWindow
method in application delegate:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
[navigationController shouldAutorotate];
[navigationController preferredInterfaceOrientationForPresentation];
return UIInterfaceOrientationMaskAll;
}
Also add this in application delegate:
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
#end
I want to know device orientation when the view will appear.
Previously it was possible using the shouldAutorotateToInterfaceOrientation method but in IOS 6 it is deprecated.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (interfaceOrientation==UIInterfaceOrientationPortrait ||interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown ) {
DashBtn.hidden=NO;
}
else
{
DashBtn.hidden=YES;
if (self.popoverControllerMain) {
[self.popoverControllerMain dismissPopoverAnimated:YES];
}
}
return YES;
}
I checked all the post
i.e making rootviewcontroller and
- (BOOL)shouldAutorotate {
return NO;
}// this method is not called
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
Create category of UINavigationController and add below code #implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
#end
Try using
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
instead of
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
refer http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html for details.
The best option to know the device orientation is
[[UIApplication sharedApplication] statusBarOrientation]