UIImagePickerController in iOS 6 doesn't work properly - ios

I'm having a very strange behavior:
in iOS 5 I present UIImagePickerController in this way:
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.modalPresentationStyle = UIModalPresentationFullScreen;
imagePicker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:imagePicker animated:YES];
now in iOS 6 this produce a crash. I resolved the crash by writing a category on UIImagePickerController:
#implementation UIImagePickerController (NonRotating)
- (BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationMaskPortrait;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
#end
The problem is that now the UIImagePickerController doesn't rotate and it's shown up-side. Moreover, when I press the "cancel" button and the picker is dismissed, the app crash again.
If I use the UIImagePickerController inside a UIPopoverController, all works fine (belonging to the fact that the popover doesn't rotate) but when I dismiss the popover ALL view controller in my app stop responding to rotation events and this cause that all app is blocked in this orientation. To restore the correct behavior I need to quit the app from the background and open again.
This is the code I'm using to display popover
_cameraPopoverController = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
[_cameraPopoverController presentPopoverFromRect:_takeFromCamera.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
This problem drive me crazy !

What is your picker source type?
Photo library/album or camera roll?
Assuming that you are using Photo Library / Album source, on iPad, you MUST use a popover:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html (look in the overview, point 4)
presenting it fullscreen is not supported.
About the other issue (after dismissing the popOver, the other VC's stops rotating) check that you have a STRONG reference to your popover (strong property).
Paste the code you are using to present the popover.

While I don't recommend using the category to override the image picker's default behavior, there is a bug in the implementation that causes the crash mentioned:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationMaskPortrait;
~~~~
}
The return value shouldn't be an orientation mask, it should be an orientation, e.g. UIInterfaceOrientationPortrait.

Related

Need help preventing UIImagePickerController rotating my portrait-only UIView in IOS13

I have an app where i'm making a UIView to take and upload images. My app is portrait only, has been for years, configured with "supported interface orientations" in my info.plist.
My problem is this, and it only happens on my iPhone 11 on IOS 13, NOT on my iphone7 running ios12.
My view is showing in portrait, like my views always do.
I have a button that opens up a UIPickerViewController like this:
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:true completion:nil];
If i then turn the camera to landscape, then take a picture OR press cancel, my UIView that previously was in portrait is now in landscape! It obviously looks super strange.
As soon as i put it in portrait, it pops back firmly in place.
Again, it only seems to happen on IOS13, but i have no idea how to solve it.
I have tried overriding shouldAutorotateToInterfaceOrientation in my UIView, it didn't help.
See below for screenshot of how it looks after the camera has rotated it.
Anybody have any thoughts?? Pointers much appreciated.
Custom a viewcontroller inherited UIImagePickerController, and overriding shouldAutorotate.
Try to use this class:
class CustomUIImagePickerController: UIImagePickerController {
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}

Wrong UI orientation on UIImagePickerController when entering camera first time

I have wrong UI orientation on UIImagePickerController when entering camera first time on iPad. Device in landscape but UIImagePickerController in portrait.
That how it's looks like
After device rotation everything is ok - UIImagePickerController gets correct UI orientation.
I have
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
and
- (BOOL)shouldAutorotate {
return YES;
}
Ok, I found an answer.
The presenting controller(UIViewController) has a property called modalPresentationStyle and it was set as UIModalPresentationFullScreen.
To resolve my problem I just set it as UIModalPresentationOverFullScreen.
presentingController.modalPresentationStyle = UIModalPresentationOverFullScreen;
Thats all.

Disable Autorotation on iOS 7 for a single presented ViewController

I have a UIViewController, which is presented modally (full screen) and I would like to disable autorotation in that view. I do not want to restrict it to landscape or portrait, just would like it to stay in whatever orientation it was originally presented.
On iOS 6 it was sufficient to just override the method:
- (BOOL)shouldAutorotate {
return NO;
}
And it did exactly what I wanted. On iOS 7 however, this seems to have no effect. The method does get called, but the return value seems to be ignored by the OS - it auto rotates no matter what.
The documentation does not mention any changes to this method. How can I achieve the desired effect on iOS 7?
Edit: the view controller is being presented (not pushed!) by a UINavigationViewController:
[self.navigationController presentViewController:vc animated:YES completion:nil];
Solution:
As odd as it may seem, but this solution was not published in the numerous existing questions on this topic. On iOS 7 it seems the answer the UINavigationController gives to
shouldAutorotate is what the OS acts on. We need to subclass UINavigationController to modify its behaviour.
When dealing with a regular navigation stack it is indeed sufficient to just use [self.topViewController shouldAutorotate], but when there is modal view, it resides in self.presentedViewController, not self.topViewController. Thus the full solution looks like:
- (BOOL)shouldAutorotate {
UIViewController *vc;
if (self.presentedViewController) vc = self.presentedViewController;
else vc = [self topViewController];
return [vc shouldAutorotate];
}
So I just tried you code and it worked which leads me to believe that you are presenting your UIViewController in a UINavigationController. For whatever reason, iOS 7 changed how UINavigationController handle rotations.
The easiest solution is to create a subclass of UINavigationController that overrides the shouldAutorotate method and returns the value from the topViewController.
#interface CustomNavigationController : UINavigationController
#end
#implementation CustomNavigationController
- (BOOL)shouldAutorotate
{
return [[self topViewController] shouldAutorotate];
}
#end
So instead of doing this, where viewController is your object that return NO for shouldAutorotate.
UINavigaitonController *navController = [UINavigationController alloc] initWithRootViewController:viewController];
[self presentViewController:navController animated:YES completion:nil];
You would use the CustomNavigationController instead
CustomNavigationController *customNavController = [CustomNavigationController alloc] initWithRootViewController:viewController];
[self presentViewController:customNavController animated:YES completion:nil];
#import <objc/message.h>
-(void)viewDidAppear:(BOOL)animated{
objc_msgSend([UIDevice currentDevice], #selector(setOrientation:), UIInterfaceOrientationPortrait );
}
see How do I programmatically set device orientation in iOS7?
But take the case you are using this method because it is a private API, and your app may be rejected by Apple. So, maybe is better to set orientation from Project details -> General -> Deployment Info tab, choose Landscape Left and Landscape Right choice only. This can be a better approach, if all your views need only one kind of orientation.

After forcing an orientation of an IOS 7 app to Portrait, nothing on the screen becomes tappable

I am seeing an issue that only happens on IOS 7 and not IOS 6, i.e. the same code works on 6 but not 7.
Basically, there is this view that I need to transition to that must be in portrait mode.
So, like many of the other examples I found on StackOverflow, the way to force an orientation would be to call this on the navigation controller :
UIViewController *mvc = [[UIViewController alloc] init];
[self presentViewController:mvc animated:NO completion:^{
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"Cleared");
[mvc.view removeFromSuperview];
[mvc removeFromParentViewController];
}];
}];
And in the target controller, I have:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
However, once I transition to this target UIViewController, nothing on that UIViewController becomes tappable at all. I am very sure that the UIButtons are linked properly because if I just load up this controller as the first controller when the app starts, the buttons all worked fine, but if I have to force an orientation on it before showing it, then the buttons don't work
I was wondering if anyone else has encountered such an issue in IOS 7 as well? This works perfectly in IOS 6
Thanks
IS

iOS 6 orientation issues

I have an application which normally is a portrait app and only show landscape view for one UIViewController. It works fine until the new iOS 6 is released.
I really don't understand how orientation works in iOS 6. So I wrote a testing app. Here is what I did:
Set the orientation of the application to support all orientations.
I'm using story board. The rootViewController is embedded in UINavigationController which is in portrait.
The code in rootViewController:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
When I clicked the Open bar button, I'll push another (SecondViewController) view controller which supposed to be in landscape mode:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
Although this method is called correctly, the second view controller is always also in portrait mode.
Can anybody give me some suggestions? Thanks
Here is my solution:
In second view controller's viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIViewController *viewController = [[UIViewController alloc] init];
[self presentViewController:viewController animated:NO completion:^{
[viewController dismissViewControllerAnimated:NO completion:nil];
}];
}
This will force the second view to rotate to landscape orientation which solved my problem. And it works for iOS 5 and 6.
For iOS-6, I have done this. It is running fine
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;}
In second View
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return YES;}
I think that best solution is to stick to official apple documentation. So according to that I use following methods and everything is working very well on iOS 5 and 6.
In all of your ViewControllers override following methods.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
Methods for iOS 6, first method returns supported orientation mask (as their name indicate), you can change it into Landscape or what suites you best.
-(NSInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait; //UIInterfaceOrientationMaskPortrait or LandscapeLeft ...
}
second one thats tells your VC which is preferred interface orientation when VC is going to be displayed.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait; //tells your VC in which orientation it should be presented, if you set Porttrait it would be in Portrait or otherwise ...
}
This solution is working smooth, I dont like the idea of creating macros and other stuffs, that goes around this simple solution.
Hope this help...

Resources