4

I have a photo app that overlays custom button on camera image picker (for taking picture, turning on/off the flash, other usual stuff etc.)

I want the control interface to support portrait orientation only (I am talking about the control button/interface only, and not the actual captured image), which was working fine till iOS 6.

However, having upgraded to xCode version 5.0 and having upgraded my iPad 3 to iOS 7 (GM Seed, for iPad WiFi 3rd Generation), I find that the camera picker interface auto-rotates when orientation is changed. Surprisingly, I tested the same build on an iPhone 5 (upgraded to iOS 7), but the auto-rotation problem did not manifest itself.

[To be double sure, I tested the same piece of code in iOS 6 again, and the auto-rotation did not happen, neither in iPhone or iPad].

Just to demonstrate how I handle my image picker, here's a bit of code snippet:

    UIImagePickerController *pickercustom = [[UIImagePickerController alloc] init];
    pickercustom.sourceType = UIImagePickerControllerSourceTypeCamera;
    pickercustom.showsCameraControls = NO;
    pickercustom.wantsFullScreenLayout = YES;
    pickercustom.navigationBarHidden=YES;
    pickercustom.view.userInteractionEnabled=YES;

    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
    {


    if (IPAD.userInterfaceIdiom == UIUserInterfaceIdiomPad)
    {
        pickercustom.delegate = self;
           UIDevice *currentDevice = [UIDevice currentDevice];
                    while ([currentDevice isGeneratingDeviceOrientationNotifications])
                        [currentDevice endGeneratingDeviceOrientationNotifications];


        [self presentViewController:pickercustom animated:YES completion:nil];

                    while ([currentDevice isGeneratingDeviceOrientationNotifications])
                        [currentDevice endGeneratingDeviceOrientationNotifications];

    }

    else
    {
        pickercustom.delegate = self;
        [self presentViewController:pickercustom animated:YES completion:nil];
    }
  }

The 'endGeneratingDeviceOrientationNotifications' was added to stop the interface from rotating (which hitherto worked fine).

I also tried adding these three methods after reading this: UIImagePickerController in iOS 6 doesn't work properly

  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
   }

  - (BOOL)shouldAutorotate
  {
    return NO;
    }

 - (NSUInteger)supportedInterfaceOrientations
  {
    return UIInterfaceOrientationMaskPortrait;
  }

...but this was, perhaps, an iOS 6 specific solution. It didn't work in my case.

Please let me know if you could figure out the root cause. It would be great help.

Community
  • 1
  • 1
metsburg
  • 2,021
  • 1
  • 20
  • 32

2 Answers2

2

You are close. When you want to support rotation but want that one viewController to not rotate, things get tricky:

The UIResponder chain REALLY wants the whole app to have the same rotation. Just simply overriding the rotation delegate methods in your single class will not work. (FYI, in your case, you will need to subclass UIImagePickerController in order to add those methods.) You need to implement these delegate methods in your root navigation controller (You'll need to have your own sub-class, again), and override them to query the top-most viewController for its desired rotation. Something like:

// Handles the should Auto Rotation for all view controllers
- (BOOL)shouldAutorotate {

    if ([self.topViewController conformsToProtocol:@protocol(CustomRotation)]) {
        return [self.topViewController shouldAutorotate];
    }

    // Auto rotate the screen by default.
    return YES;
}

// Handles the supported Interface Orientations for all View Controllers by seeing if
// the top level viewController responds to Custom Rotation callbacks.
- (NSUInteger)supportedInterfaceOrientations {
    if ([self.topViewController conformsToProtocol:@protocol(CustomRotation)]) {
        return [self.topViewController supportedInterfaceOrientations];
    }

    // The default rotation for the application.
    return UIInterfaceOrientationMaskAll;
}

You can't use respondsToSelector: in place of conformsToProtocol: because the selector method will always return YES for any class that derives from UIResponder (so like, everything), and you'll have to override the rotation delegates on each and every UIViewController in your project to make this work. Instead, you can create a blank protocol (CustomRotation). In your custom rotation class require that protocol and include the overridden rotation delegate methods like you have above, with the your desired restrictions.

Lastly make sure your supported interface orientations are set properly in xcode and/or in your Application: didFinishLaunchingWithOptions method.

Austin
  • 439
  • 3
  • 10
2

As far as R&D done by me for the same topic,Imagepicker Camera in IOS7 iPad have default interface to change orientation to landscape .They have designed interface in such a way.We cannot forcefully lock the orientation of it.

If still willing to do you have to use custom ImagePicker use AVCam https://developer.apple.com/library/ios/samplecode/avcam/Introduction/Intro.html

and Custom image picker... http://www.codza.com/custom-uiimagepickercontroller-camera-view

and forcefully lock there orientation...

Parvez Belim
  • 1,003
  • 13
  • 36