Application is enabled only to Portrait, but UIImagePickerController rotates in iOS6 - iphone

Please note that the answer below - do not work for iOS6 so I still need an answer!
My application is enabled only for Portrait mode.
However, if I embed a UIImagePickerController inside as a subview, and rotate the device, the top and bottom bar stays in the same location, however UIImagePickerController does rotate.
How can I prevent it from rotating?
This is the code:
[self.view.window addSubview:self.imagePickerController.view];
self.imagePickerController.showsCameraControls = NO;
self.imagePickerController.view.frame = CGRectMake(0, 90, 320, 320);
self.imagePickerController.allowsEditing = NO;
EDITED
I am using iOS6 where shouldAutorotate is not being calle

Add this UIImagePickerController category in your class,
#interface UIImagePickerController(Nonrotating)
- (BOOL)shouldAutorotate;
#end
#implementation UIImagePickerController(Nonrotating)
- (BOOL)shouldAutorotate {
return NO;
}
#end

include the following in your controller this will work, I'm just creating the category of UIImagePickerController
#interface UIImagePickerController (private)
- (BOOL)shouldAutorotate;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
- (NSUInteger)supportedInterfaceOrientations;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
#end
#implementation UIImagePickerController (Private)
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

One possibility is to override the
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
method of UIImagePickerController. I'm not sure if this is the best possibility but it will work.
So if you only want your UIImagePickerController to be rotated to portrait use the following code
#interface PortraitUIImagePickerController : UIImagePickerController
#end
And the implementation should look like the following
#implementation PortraitUIImagePickerController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
#end

The category in the most voted answer works, but since it is discouraged to use categories, you can also make a subclass of UIImagePickerController and use that.
If you want to avoid rotating of the UIImagePickerController add the following class
UINonRotatableImagePickerController.h
#interface UINonRotatableImagePickerController : UIImagePickerController
#end
UINonRotatableImagePickerController.m
#implementation UINonRotatableImagePickerController
- (BOOL)shouldAutorotate
{
return NO;
}
#end
You have to change the UIImagePicker class in the storyboard to use UILandscapeImagePickerController, or if you allocate it in code, change
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
to
UIImagePickerController *picker = [[UINonRotatableImagePickerController alloc] init];
and include UINonRotatableImagePickerController.h in your code.

Related

How to block rotation in ios 7

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.

Force portrait orientation while pushing from landscape View Controller

App Support: iOS6+
My app works in both portrait and landscape. But 1 controller should only works in a Portrait.
The problem is that when I am in landscape and push the view controller the new viewcontroller is in landscape as well until I rotate it to portrait. Then it's stuck in portrait as it should be.
Is it possible to always make it appear in portrait? Even if its parent is pushing it in landscape?
All the following code doesn't help
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
And this code works until and unless i am not pushing from landscape How to force a UIViewController to Portrait orientation in iOS 6
I solved this by adding following lines in ViewDidLoad
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:c animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
First, you need to create a category:
UINavigationController+Rotation_IOS6.h
#import <UIKit/UIKit.h>
#interface UINavigationController (Rotation_IOS6)
#end
UINavigationController+Rotation_IOS6.m:
#import "UINavigationController+Rotation_IOS6.h"
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
Then, you implement these methods in your class that you want to be only landscape:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
In case you're using a UITabBarController, just replace the UINavigationController for UITabBarController.
This solution worked nice for me after a long search! I was in the same situation as you are now!
EDIT
So, I saw your sample. You need to make some changes.
1 - Create a new class for the UINavigationController category. Name the class UINavigationController+Rotation_IOS6 (.h and .m)
2 - You don't need to implement the method preferredInterfaceOrientationForPresentation. Your category should look like this:
#import "UINavigationController+Rotation_IOS6.h"
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
3 - In the class you want to rotate only in landscape, include this in the implementation, exactly like this:
// Rotation methods for iOS 6
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
4 - I would advice to also include the method for autorotation for iOS 5 inside the class you want in landscape:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}

MPMoviePlayerController full screen orientation issue

My app supports only Landscape. I've added an MPMoviePlayerController to the view of my view controller.
When I press full screen button, it works fine and it will rotate in Landscape only for iOS versions prior to iOS 5. However, in iOS 5.0+, it also supports portrait (only when I enter into full screen mode).
How can I prevent portrait support in iOS 5.0 and above?
Try subclassing MPMoviePlayerViewController and overriding the shouldAutorotatoToInterfaceOrientation method to only support landscape modes:
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
return true;
}
else
{
return false;
}
}
I resolved this problem thus: create custom navigation controller what support 2 orientation:
UIInterfaceOrientationLandscapeLeft && UIInterfaceOrientationLandscapeRight
More details:
1. Create custom navigation controller
CustomNavigationController.h file
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController;
#end
CustomNavigationController.m file
#implementation IORNavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
2.In Appdelegate add self navigation controller
Appdelegate.h
#property (nonatomic, retain) CustomNavigationController* navigationController;
Appdelegate.m
self.navigationController = [[[CustomNavigationController alloc] initWithRootViewController:start] autorelease];
self.navigationController.view.autoresizesSubviews = YES;
window.rootViewController = self.navigationController;
[self.navigationController setNavigationBarHidden:YES];
And now you have app with two orientation and video in landscape orientation.

Making a created (programmatically) viewController Rotate

I have made a viewController programmatically and I want to force it to rotate whenever the device is rotated .
in simple viewController you create using the normal way by adding a new file and so there a "shouldAutoRotate" method ..
but in my case it's different especiall that I create this viewController in a viewController!
and I don't want to create a new viewController.
this is the code I used to create the viewcontroller
UIViewController *featuresViewController = [[UIViewController alloc]initWithNibName:#"featrures" bundle:nil];
[featuresViewController setView:[[UIView alloc]initWithFrame:CGRectMake(10, 10, 380, 450 )]];
[featuresViewController.view setBackgroundColor:[UIColor clearColor]];
featuresViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
featuresViewController.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController:featuresViewController animated:YES];
Easier to add this as another answer...
Probably not the best place to do this, but if you're struggling on how to code your FeaturesViewController, it'll be something like this -
.h -
#import <UIKit/UIKit.h>
#interface FeaturesViewController : UIViewController {
// ivar declarations...
}
#end
.m -
#import "FeaturesViewController.h"
#implementation FeaturesViewController
-(id)init {
self = [super initWithNibName:#"FeaturesViewController" bundle:nil];
if (self) {
// other init stuff
}
return self;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// return YES for whatever orientations you want
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
Then in your main VC, present it like this -
FeaturesViewController *featuresViewController = [[[FeaturesViewController alloc] init] autorelease];
featuresViewController.modalTransitionStyle=UIModalTransitionStylePartialCurl;
featuresViewController.modalPresentationStyle=UIModalPresentationPageSheet;
[self presentViewController:featuresViewController animated:YES completion:nil];
Add following code in you application...
//add following line before #implementation
#interface UIDevice (UndocumentedFeatures)
-(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
-(void)setOrientation:(UIInterfaceOrientation)orientation;
#end
//here you can use following code in any method..i just used here in sample method...
-(IBAction)rotateviewprogramatically
{
**//you can also add this in Viewdidload or Viewwillappear...it will work...**
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
//or
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
// Change following code.... add following method in you code...i checked it's working...
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);// don't use this
return YES; // use this...
}
Hope, it will help you...chill
I don't understand what you mean when you say you create the viewController in a viewController - I think where you create it is irrelevant. It's also irrelevant that you create it programmatically, as you still have to have written the code...
In your VC's code, simply implement the normal shouldAutorotateToInterfaceOrientation: method (this example allows either of the landscape orientations) -
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

iOS - QLPreviewController - How to stop QuickLook from Rotating?

I have QuickLook (QLPreviewController) almost working how I want it, but because of the images characteristics I don't want it to rotate into portrait orientation.I have it configured in the "shouldAutoRotateToInterfaceOrientation" method to only return yes for landscape rotations (see code below for details) but it is still rotating to portrait.
Note: The shouldAutoRotateToInterfaceOrientation is a direct copy that is used in all of my view controllers for this project and it is working in the other view controllers.
//
// documentViewer.m
//
#import "DocumentViewer.h"
#implementation DocumentViewer
#synthesize documents;
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
return YES;
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight)
return YES;
else
return NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
//-(void)viewWillAppear:(BOOL)animated {
//
// self.userInteractionEnabled = YES;
//}
//Nessary for Enabling User Interaction
- (BOOL)canBecomeFirstResponder {
return YES;
}
-(void) createList:(NSString *) document {
documents = [[NSArray arrayWithObjects:document, nil] retain];
}
-(NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller {
return [documents count];
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index {
return [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[documents objectAtIndex:index] ofType:nil]];
}
#end
In AppDelegate.m replace
return UIInterfaceOrientationMaskAll;
with
return UIInterfaceOrientationMaskLandscape;
just like this:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskLandscape;
}
According to the ViewController Programming Guide for iOS, the autorotation is roughly controlled by the ViewController that was most recently made visible.
In your case that's probably the QLPreviewController itself, not your DocumentViewer. (And you say that the latter's shouldAutorotateToInterfaceOrientation: isn't called, which is consistent with this hypothesis).
So the autorotation is controlled by the shouldAutorotateToInterfaceOrientation: method of QLPreviewController, which in a little experiment of mine seems to allow everything but upside-down orientation.
So what you can do is define a subclass of QLPreviewController that only overrides shouldAutorotateToInterfaceOrientation: the way you did in DocumentViewer and use this subclass instead of the original QLPreviewController.
LandscapeOnlyQLPreviewController.h:
#import <QuickLook/QuickLook.h>
#interface LandscapeOnlyQLPreviewController : QLPreviewController {
}
#end
LandscapeOnlyQLPreviewController.m:
#import "LandscapeOnlyQLPreviewController.h"
#implementation LandscapeOnlyQLPreviewController
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
#end
I never did find a good answer, so I ended up just using a UIWebView.
But I'm still looking.
Try this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}