My app is structured with a central view controller that adds 3 to 4 subviews to the main view. In one of the added view controllers I present a camera to the user. When I dismiss the image picker, every subview except the one in which I present the camera (the view controller) disappears. I think it might be related to how the app is structured and the view stack. The app works fine when running iOS 8 on an iPhone and iOS 7 on an iPad. I am having this issue only when I am running iOS 8 on the iPad. I made sure the code followed the apple documentation on how to present and dismiss the image picker. Here is the code used to present the image picker.
-(IBAction)photoButtonPressed:(id)sender
{
// Prompt for camera or photo library
// Retrieve image and set it as this button's default image
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage, nil];
imagePicker.allowsEditing = NO;
imagePicker.modalPresentationStyle = UIModalPresentationFullScreen; //play around with this
[self presentViewController:imagePicker animated:YES completion:nil];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Camera not found" message:#"There is no camera available on this device." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
Code used to dismiss
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
CGSize scaleSize = CGSizeMake(1024.0f, 1280.0f);
UIImage *capturedImage;
// Handle a still image capture
capturedImage = (UIImage *) [info objectForKey:
UIImagePickerControllerOriginalImage];
[self dismissViewControllerAnimated:YES completion:nil];
if (capturedImage) {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
photoData = UIImageJPEGRepresentation([capturedImage resizedImage:scaleSize interpolationQuality:kCGInterpolationHigh], 5);
photoEntity = nil;
[self.takePhotoButton setImage:[UIImage imageWithData:photoData ] forState:UIControlStateNormal];
if ([self isAnyButtonSelected] || ![_answerTextField.text isEqualToString:#""] || !_questionBoolean.hidden) {
[Tools enableControl:_saveButton];
}
} else {
newPhotoData = UIImageJPEGRepresentation([capturedImage resizedImage:scaleSize interpolationQuality:kCGInterpolationHigh], 5);
photoEntity = nil;
}
}
}
And here I tried messing with the parent views and controllers in this method. I was able to get the app to return to the central view controller minus the current view controller that is in charge of taking the photos. The only problem is that the app's touch is now disabled and I am missing one view.
- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker
{
// [self willMoveToParentViewController:nil];
// [picker.view removeFromSuperview];
// [picker removeFromParentViewController];
[self dismissViewControllerAnimated:YES completion:nil];
}
I was going to post photos but I am currently unable to because I am new to stack overflow. Any help would be appreciated. Thanks!
Ok so the app is not using story boards but it is using xib files. It is inherited code and the app was created several years ago. There are multiple view controllers with multiple views. There is a central view controller where all the other view controllers are added to the central view.
[self.view addSubview:_catViewController.tableView];
[self.view addSubview:_listViewController.tableView];
[self.view addSubview:_queryViewController.view];
[self.view bringSubviewToFront:_queryViewController.view];
queryViewController is where I am taking the photo. When I dismiss every view is gone except the query view controller which happens to take up the entire screen (it previously did not). Let me know if I need to add more information! Thanks
So, the general problem is that your central view controller is adding the views of other view controllers to itself. You can't do that -- it breaks view controller encapsulation. And when you violate encapsulation, stuff just breaks. (That's a vague statement, but 100% true :-p) Unfortunately, you either need to stab in the dark to find a hack to make it work, or repartition the problem to respect encapsulation. The latter is probably better if you'll need to maintain this code in the future.
I have an iPad app that only supports landscape orientations, however when I try to display a UIImagePickerController inside a UIPopoverController it always appears in portrait mode. i.e. rotated 90 degrees from the rest of the UI. Does anyone know how I can make this appear in the same orientation as the ViewController I'm presenting it in?
I'm displaying the imagePicker like this:
self.picker = [[FFSImagePicker alloc] init];
picker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
picker.delegate = self;
picker.toolbarHidden = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = NO;
picker.showsCameraControls = YES;
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
self.photoPickerPopover = popover;
[self.photoPickerPopover presentPopoverFromRect:photoButton.bounds inView:photoButton permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
FFSImagePicker is just a subclass of UIImagePickerController where I tried to make sure the supported orientations were only landscape, but that had no effect.
Thanks for any help...
OK, I solved this, the issue was that I was presenting the UIImagePickerController in a UIPopover which Apple says not to do when the source type is the camera, instead present it full screen just like you would any other view controller.
Hope this helps someone else too...
I am creating an app which is in landscape mode and I am using UIImagePickerController to take photos using iPhone camera in it and I want to create it in landscape mode too.
But as the Apple documention suggests UIImagePickerController does not support landscape orientation, so what should I do to get desired functionality?
If you'd like to use UIImagePickerController in landscape mode, use user1673099's answer, but instead of:
- (BOOL)shouldAutorotate
{
return NO;
}
use:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
and then the picker would open in landscape mode:
But make sure you check Portrait in deployment info:
... and I want to create it in landscape mode too.
One line of code can make a big difference! In the method or function where your IBAction lands:
In Swift,
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
// .overCurrentContext allows for landscape and portrait mode
imagePickerController.modalPresentationStyle = .overCurrentContext
Objective-C,
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
[imagePickerController setModalPresentationStyle: UIModalPresentationOverCurrentContext];
Note: This will allow imagePickerController to present it's view correctly, but will may not fix the issue of rotation while it is presented.
Try this way....
As per Apple Document, ImagePicker Controller never Rotate in Landscape mode. You have to use in Portrait Mode only.
For disable Landscape mode only for ImagePicker Controller follow below code:
In your ViewController.m:
Make the SubClass(NonRotatingUIImagePickerController) of Image Picker Controller
#interface NonRotatingUIImagePickerController : UIImagePickerController
#end
#implementation NonRotatingUIImagePickerController
// Disable Landscape mode.
- (BOOL)shouldAutorotate
{
return NO;
}
#end
Use as follow
UIImagePickerController* picker = [[NonRotatingUIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
etc.... Just as Default ImagePicker Controller
This is working for me & Let me know if you have any Problem.
This works great with Swift 4.0 in iOS 10/11.
import UIKit
extension UIImagePickerController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
}
Just drop the extension somewhere in your project, no need to subclass anything for it to work.
If you do need to specify device types, you can add a check like this:
import UIKit
extension UIImagePickerController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIDevice.current.userInterfaceIdiom == .phone ? .portrait : .all
}
}
This will allow an iPad to freely rotate, but enforces portrait mode on a phone. Just make sure that your app is configured to support these in its info.plist, otherwise you may encounter crashes upon launching the picker.
Here's a version that supports rotation in all interface orientations:
/// Not fully supported by Apple, but works as of iOS 11.
class RotatableUIImagePickerController: UIImagePickerController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
}
This way if the user rotates her device, it'll update the picker controller to support the current orientation. Just instantiate as you normally would a UIImagePickerController.
If you only want to support a subset of orientations, you can return a different value.
The correct way to use UIImagePickerController in landscape mode without any hacks is to put it into a UIPopoverController
- (void)showPicker:(id)sender
{
UIButton *button = (UIButton *)sender;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[_popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Modify above code method
- (NSUInteger)supportedInterfaceOrientations
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
return UIInterfaceOrientationMaskLandscape;
else
return UIInterfaceOrientationMaskPortrait;
}
Accepted answer doesn't work for me. I had also to add modalPresentationStyle to UIImagePickerController to make it working.
UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
pickerController.modalPresentationStyle = UIModalPresentationCurrentContext; //this will allow the picker to be presented in landscape
pickerController.delegate = self;
pickerController.allowsEditing = YES;
pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:pickerController animated:YES completion:nil];
And of course remember to put this in a controller that presents the picker:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape; //this will force landscape
}
But according to Apple's documentation this is not supported to present this picker in the landscape mode so be careful about it.
If you're looking for SwiftUI solution in conjunction with the things mentioned here check this out here. Ignoring the safe area for the UIImagePickerController representable resolved a lot of my issues.
I have looking for a complete tutorial on google and stack of a complete example on using the UIImagePicker to get a picture from the camera and a picture from the library or camera roll on the iPad 2.
I have found code snippets saying just add the PopOverController in, but have not been able to implement it successfully.
thanks in advance.
This worked for me.
I do it like this I detect if iPhone or iPad and in the popover where it says (self.album.bounds) is just were you want the popover arrow to appear in this case self.album is the button that fires the below action
-(IBAction)selectPicture:(id)sender {
NSLog(#"Image is not set");
// Create image picker controller
thePicker = [[UIImagePickerController alloc] init];
// Set source to the camer roll;
thePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// Delegate to self
thePicker.delegate = self;
//Allow editing of image NO
thePicker.allowsEditing = NO;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
[self presentModalViewController:thePicker animated:YES];
}
else{
popover = [[UIPopoverController alloc]initWithContentViewController:thePicker];
[popover presentPopoverFromRect:self.album.bounds inView:self.album permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
popover = popover;
}
}
I have been beating my head on this for a few hours. I have some sample code (using a UINavigationController) when the view loads the camera roll will be presented. However, when I try to incorporate the same code into my app, which has a tabBarController, I get a blank modal UIImagePickerController. I didn't track down what I am doing wrong.
// bring up image picker
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
NSLog(#"UIImagePickerControllerSourceTypePhotoLibrary available");
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
ipc.delegate = self;
ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
ipc.allowsEditing = YES;
[self.tabBarController presentModalViewController:ipc animated:YES];
[ipc release];
}
Any insight would be appreciated.
Not sure what has changed, but this is possible by calling presentViewController from your tabBarController. This is the standard now and ensures your camera or image picker always gets presented as a full screen modal view.
For reference: presentViewController