How to block rotation in ios 7 - iphone

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.

Related

How to allow only single UIViewController to rotate in both Landscape and Portrait direction?

My app is only for iphone device (both iphone 4 and 5) and built to support only ios 6.
My whole app only supports portrait mode. But there is one view called "ChatView" , which i want to support both landscape and portrait modes.
I have set the required device rotations as follows -
I have also tried following code to support rotation in "ChatView" -
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
But it could not rotate that view.
I have searched a lot for this , but could not be able to find the solution for my issue.
And also in "ChatView" there are some objects like buttons, textfields whose frames are set programmaticaly. So i want to know should i have to set frames of all those objects for landscape mode also?
Please help me.
Thanks.....
Simple but it work very fine. IOS 7.1 and 8
AppDelegate.h
#property () BOOL restrictRotation;
AppDelegate.m
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskAll;
}
ViewController
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
viewDidLoad
[self restrictRotation:YES]; or NO
I think if you want to support just one viewcontroller rotation, it is not possible since application will follow orientations set by you in .plist file. An alternate you can follow is to support your app for both landscape and portrait, freeze all viewcontrollers rotation to portrait except for chat view.
EDIT
To subclass UINavigationController, create a new file with name e.g. CustomNavigationController and make it subclass of UINavigationController.
.h file
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController
#end
.m file
#import "CustomNavigationController.h"
#interface CustomNavigationController ()
#end
#implementation CustomNavigationController
-(BOOL)shouldAutorotate
{
return NO;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
#end
Set the class of your UINavigationController in your main class xib as CustomNavigationController. Hope it helps ypu..
Your view controller will never rotate to any position that is not supported by the app itself. You should enable all possible rotations and then in view controllers that are not supposed to rotate put the following lines
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
In ChatView, it should be:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
If you need to change your layout after a rotation you should implement the appropriate changes to your subviews in
- (void)viewWillLayoutSubviews
Use self.view.bounds to check the current size of the view, since self.view.frame doesn't change after rotations.
for the specific viewcontroller.m you want to rotate
add this method:
- (BOOL)canAutoRotate
{
return YES;
}
then inside your AppDelegate.m
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UIViewController *currentViewController = [self topViewController];
if ([currentViewController respondsToSelector:#selector(canAutoRotate)]) {
NSMethodSignature *signature = [currentViewController methodSignatureForSelector:#selector(canAutoRotate)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:#selector(canAutoRotate)];
[invocation setTarget:currentViewController];
[invocation invoke];
BOOL canAutorotate = NO;
[invocation getReturnValue:&canAutorotate];
if (canAutorotate) {
return UIInterfaceOrientationMaskAll;
}
}
return UIInterfaceOrientationMaskPortrait;
}
- (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;
}
}
Ted's answer works well with the issue mentioned by Alexander of Norway.
But I figured that issue is not happening the way Alexander explained,
When ViewController B which currently is in landscape (All
orientations enabled) returns back to ViewController A. (Portrait
only) after the user clicks on the back button,
supportedInterfaceOrientationsForWindow doesn't get called and
ViewController A ends up in landscape
Actually when ViewController B which currently is in landscape (All orientations enabled) returns back to ViewController A (Portrait only) after the user clicks on the back button, Appdelegate
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
is getting called. But still root view controller is ViewController B (that rotation enabled view controller), ViewController A is not getting back to portrait orientation, since ViewController B is still returning
-(BOOL)shouldAutorotate{
return YES;
}
So when you press back button return, "shouldAutorotate -> NO" in ViewController B. Then ViewController A will come to Portrait orientation. This is what I did
#property (nonatomic, assign) BOOL canAutoRotate;
#pragma mark - Public methods
- (BOOL)canAutoRotate
{
return _canAutoRotate;
}
#pragma mark - Button actions
- (void)backButtonPressed:(UIButton *)sender {
_canAutoRotate = NO;
(...)
}
#pragma mark - Init
- (id)init{
if(self=[super init]) {
_canAutoRotate = YES;
}
return self;
}
Swift 3 Kosher Version
I've left this here just for a case somebody has the problem.
Apple's documentation for supportedInterfaceOrientations says:
When the user changes the device orientation, the system calls this method on the root view controller or the topmost presented view controller that fills the window. If the view controller supports the new orientation, the window and view controller are rotated to the new orientation. This method is only called if the view controller's shouldAutorotate method returns true.
In few words you have to override supportedInterfaceOrientations in root view controller so that it returns the value for its top child view controller and default value otherwise.
What you should do is checking if app supports all modes (go to Deployment info in targets General settings or Info.plist), find out the class of your root view controller. It can be generic UIViewController, UINavigationController, UITabBarController or some custom class. You can check it out this way:
dump(UIApplication.shared.keyWindow?.rootViewController)
Or any other way you like.
Let it be some CustomNavigationController. So you should override supportedInterfaceOrientations like this:
class CustomNavigationController: UINavigationController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
}
}
In any view controller which should support only portrait orientation for instance override supportedInterfaceOrientations this way:
class ChildViewController: UIViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}
Then don't forget to check if shouldAutorotate of you root view controller and topmost presented view controller already returns true. If not, add this to classes definitions:
override var shouldAutorotate: Bool {
return true
}
Otherwise supportedInterfaceOrientations will nor be called at all.
Here you go!
If you need to fix the opposite problem when only one view controller should support a bunch of orientations and others don't, make this changes to every view controller but this one.
Hope this will help.
I know this questions is very old but It needs an updated answer. The easiest and most correct way to achieve this result is to enable Portrait and Landscape in your app settings. Then add this code to your app delegate:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if let navigationController = self.window?.rootViewController as? UINavigationController {
if navigationController.visibleViewController is INSERTYOURVIEWCONTROLLERHERE {
return UIInterfaceOrientationMask.All
}
else {
return UIInterfaceOrientationMask.Portrait
}
}
return UIInterfaceOrientationMask.Portrait
}
Dont forget to replace "INSERTYOURVIEWCONTROLLERHERE" with your view controller.
I'm not sure about the history of this issue (now = iOS 10 timeframe), but the easiest solution was missing as I posted this in Oct. 2016.
Assuming you want this:
Supporting iOS 7 and newer only (including iOS 10)
Some view controllers should support all orientations, others should support a subset of orientations. Example of what I mean: one view controller should only support portrait, while all others should support all orientations
All view controllers must auto-rotate if they support rotation (meaning, you don't want the code that fixes this issue in your view controllers)
Support adding UINavigationControllers in XIBs/NIBs/Storyboards without having to do anything to them
... then (IMO) the easiest solution is to make a UINavigationControllerDelegate, NOT sub-class UINavigationController (which violates assumption 4 above).
When I solved this, I decided to make my first ViewController a UINavigationControllerDelegate. This view controller sets itself as the navigation controller's delegate, and returns which orientations are allowed. In my case the default is that all orientations are allowed, with portrait preferred, but in one particular case only portrait is allowed. Code below is from Swift 3 / XCode 8:
class iPhoneStartViewController: UIViewController {
var navInterfaceOrientationMask: UIInterfaceOrientationMask?
var navInterfaceOrientationPreferred: UIInterfaceOrientation! = .portrait
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
#IBAction func cameraButtonPressed(_ sender: AnyObject) {
if PermissionsHelper.singleton().photosPermissionGranted() == false {
self.navInterfaceOrientationMask = nil // default is: all orientations supported
self.performSegue(withIdentifier: "segueToPhotoAccess", sender: self)
} else {
self.navInterfaceOrientationMask = .portrait // this stops the next view controller from being to rotate away from portrait
self.performSegue(withIdentifier: "segueToCamera", sender: self)
}
}
}
// lock orientation to portrait in certain cases only. Default is: all orientations supported
extension iPhoneStartViewController : UINavigationControllerDelegate {
public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
if let mask = self.navInterfaceOrientationMask {
return mask
} else {
return .all
}
}
public func navigationControllerPreferredInterfaceOrientationForPresentation(_ navigationController: UINavigationController) -> UIInterfaceOrientation {
return self.navInterfaceOrientationPreferred
}
}
Based on #iAnum's answer, I've enabled autorotate and UIViewController class detection.
This is because otherwise transitioning into and out of the "special view controller" won't correct to portrait orientation, and you'll be stuck in an unsupported orientation.
I only had one view supporting landscape, so I just hard-coded it in the custom navigation view controller:
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
//Access the current top object.
UIViewController *viewController = [self.viewControllers lastObject];
//Is it one of the landscape supported ones?
if ([viewController isMemberOfClass:[SpecialViewController class]]) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
} else
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//Access the current top object.
UIViewController *viewController = [self.viewControllers lastObject];
//Is it one of the landscape supported ones?
if ([viewController isMemberOfClass:[SpecialViewController class]]) {
return interfaceOrientation;
} else
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
There's a problem popping VCs discussed here https://stackoverflow.com/a/15057537/1277350 where pressing back while in landscape won't even call the orientation methods, so you've got to hack it a bit by showing and dismissing a modal view.
And then just remember that if you want willShowViewController to fire, you need to set self.delegate = self and add the UINavigationControllerDelegate to your custom navigation controller along with the code below.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[UIViewController alloc]init];
[c.view setBackgroundColor:[UIColor clearColor]];
[navigationController presentViewController:c animated:NO completion:^{
[self dismissViewControllerAnimated:YES completion:^{
}];
}];
}
}
make a subclass of UINavigationController like so:
MyNavigationController.h
#import <UIKit/UIKit.h>
#interface MyNavigationController : UINavigationController
#end
MyNavigationController.m
#import "MyNavigationController.h"
#import "ServicesVC.h"
#implementation MyNavigationController
-(BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
if ([[self.viewControllers lastObject] isKindOfClass:[ServicesVC class]]) {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
return UIInterfaceOrientationMaskAll;
}
#end
assuming that your viewcontroller is named: ServicesVC
Here is the answer of Alexander (https://stackoverflow.com/posts/25507963/revisions) in Swift:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
var currentViewController: UIViewController? = self.topViewController()
if currentViewController != nil && currentViewController!.canAutoRotate() {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
func topViewController() -> UIViewController? {
if UIApplication.sharedApplication().keyWindow != nil
{
return self.topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
}
return nil
}
func topViewControllerWithRootViewController(rootViewController: UIViewController?) -> UIViewController? {
if rootViewController == nil {
return nil
}
if rootViewController!.isKindOfClass(UITabBarController) {
var tabBarController: UITabBarController = (rootViewController as? UITabBarController)!
return self.topViewControllerWithRootViewController(tabBarController.selectedViewController)
}
else {
if rootViewController!.isKindOfClass(UINavigationController) {
var navigationController: UINavigationController = (rootViewController as? UINavigationController)!
return self.topViewControllerWithRootViewController(navigationController.visibleViewController)
}
else {
if (rootViewController!.presentedViewController != nil) {
var presentedViewController: UIViewController = rootViewController!.presentedViewController!
return self.topViewControllerWithRootViewController(presentedViewController)
}
else {
return rootViewController
}
}
}
}
In addition, you will need to add the following snippet in AppDelegate.swift:
extension UIViewController {
func canAutoRotate() -> Bool {
return false
}}
And for ViewControllers for which you want to allow all rotations, add this function:
override func canAutoRotate() -> Bool {
return true
}
// paste this method in app deligate class
- (UIInterfaceOrientationMask)application:(UIApplication )application supportedInterfaceOrientationsForWindow:(UIWindow )window
{
if ([self.window.rootViewController.presentedViewController isKindOfClass: [_moviePlayerController class]])
{
if (self.window.rootViewController.presentedViewController)
return UIInterfaceOrientationMaskAll;
else return UIInterfaceOrientationMaskPortrait;
}
else return UIInterfaceOrientationMaskPortrait;
}
I had the same situation. So I subclassed UINavigationController into CustomNavigationController, and inside this CustomNavigationController, I wrote
#define IOS_OLDER_THAN_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] < 6.0 )
#define IOS_NEWER_OR_EQUAL_TO_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 6.0 )
#pragma mark - Rotation
#ifdef IOS_OLDER_THAN_6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
#endif
#ifdef IOS_NEWER_OR_EQUAL_TO_6
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;;
}
#endif
I used this CustomNavigationController instead of existing NavigationController.
Then inside the view controller that you have to display in LandScape Orientation say LandScapeView, I wrote
#pragma mark - Rotation
#ifdef IOS_OLDER_THAN_6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight | toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
#endif
#ifdef IOS_NEWER_OR_EQUAL_TO_6
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
#endif
Inside CustomNavigationController, I presented this view controller, not pushed into Navigation Stack. So the LandScapeView appeared in LandScape Orientation.
LandScapeView *graph = [[LandScapeView alloc]init....];
[self presentViewController:graph animated:YES completion:nil];
I did not change anything in the Supported Interface Orientation in Project Settings.
If the App is supporting from IOS7 to IOS9 use this code for Orientation:
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
#endif
{
if([AppDelegate isPad]) return UIInterfaceOrientationMaskAll;
else return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

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;
}

Alternate landscape triggered at unwanted view

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.

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.

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);
}