I saw a strange behaviour today. I was trying to open uiimagepickercontroller from a viewcontroler called lets say "BloodWingViewController (subclass of viewcontroller)". Here is the code to display picker:
if (self.picker == nil) {
[SVProgressHUD showWithStatus:#"Loading picker..."];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
self.picker = [[[UIImagePickerController alloc] init] autorelease];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker.allowsEditing = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController presentModalViewController:picker animated:YES];
[SVProgressHUD dismiss];
});
});
} else {
[self.navigationController presentModalViewController:picker animated:YES];
}
Well above code works absolutely fine, no problem with that. The strange thing i saw was if i get into this so called "BllodWingViewController" through push seague and try to open picker then it works. But if i get into again so called "BllodWingViewController" through modal seague and try to open picker then it doesnt work at all. No picker opens up. Can u explain me the reason behind this ? And How to overcome this issue since i have to open picker from viewcontroller that has been exec via modal seague connection.
Sorry for my english if it confuses you :P
EDIT:
- (IBAction)onPhotoPickerClick:(id)sender {
if (self.picker == nil) {
[SVProgressHUD showWithStatus:#"Loading picker..."];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
self.picker = [[[UIImagePickerController alloc] init] autorelease];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker.allowsEditing = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController presentModalViewController:picker animated:YES];
[SVProgressHUD dismiss];
});
});
} else {
[self.navigationController presentModalViewController:picker animated:YES];
}
}
#import <UIKit/UIKit.h>
#interface EditStudentViewController : UIViewController{
UIImagePickerController * picker;
}
(IBAction)onPhotoPickerClick:(id)sender;
#property (retain, nonatomic) UIImagePickerController * picker;
#end
Now when i am coming to EditStudentViewController using push segue connection, onPhotoPickerClick is working, means photolibary shows up and i can select images. But when i come to EditStudentViewController from previous viewcontroller then photolibary doesnt shows up at all.
Thanks.
Related
Edit - I solved this myself - see the notes at the bottom
When using iOS7 on Xcode 5, I am using an option to take an image from a camera, or from the photo library, once the image is chosen (or a new picture taken) the view should flip over to the next screen.
This does not happen on the iPhone running iOS7, it works fine on the iPad, but the method is slightly different, but it does appear to be iPhone only problem on iOS7.
here is the code used, for example, on the choose image from library function;
-(void) choosePic {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
cameraUI.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeSavedPhotosAlbum];
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
_popover = [[UIPopoverController alloc] initWithContentViewController:cameraUI];
[_popover presentPopoverFromRect:btnLibrary.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else
[self presentModalViewController: cameraUI animated: YES];
}
}
Also, the code once picker is finished;
- (void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info {
//Disable buttons
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self disableButtons];
//Get image
self.originalImage = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];
//Dismiss
if(_popover)
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
[_popover dismissPopoverAnimated:YES];
_popover = nil;
}
}
else
[picker dismissModalViewControllerAnimated: YES];
//Next
[self performSelector: #selector(nextScreen) withObject:nil afterDelay:0.5];
}
I fixed this by switching out;
[picker dismissModalViewControllerAnimated: YES];
With
[picker dismissViewControllerAnimated:NO completion:nil];
First you need to make sure that logic reaches the correct place it's intended to, try setting a breakpoint or NSLog before the iPhone's specific line, try this (You also missed curled braces, added them here) :
-(void) choosePic {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
cameraUI.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeSavedPhotosAlbum];
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
_popover = [[UIPopoverController alloc] initWithContentViewController:cameraUI];
[_popover presentPopoverFromRect:btnLibrary.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}else{
NSLog(#"Checkpoint !");
[self presentModalViewController: cameraUI animated: YES];
}
} }
I have created an application for capture image from camera. This is my code
-(IBAction) showCameraUI {
BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = hasCamera ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
}
And implemented this delegate method for get the captured image
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImage *yourImageView = image;
}
Implemented this method if user cancel the controller
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
{
[picker dismissModalViewControllerAnimated:YES];
}
But it shows this exception. Does anyone have any idea why it is showing such exception after executing last line of function showCameraUI.
UIStatusBarStyleBlackTranslucent is not available on this device. 2013-02-07
10:06:06.976 CaptureImage[460:c07] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'On iPad, UIImagePickerController must be
presented via UIPopoverController'
Regarding the exception, the error message is very clear. "On iPad, UIImagePickerController must be presented via UIPopoverController" For iPad, you should present it in a UIPopoverController instead of using [self presentModalViewController:picker animated:YES];. This should fix the issue.
For eg:-
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[popover presentPopoverFromRect:self.view.bounds inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popover = popover;
} else {
[self presentModalViewController:picker animated:YES];
}
Edit: As mentioned by #rmaddy, camera can be presented modally. The above is applicable when sourceType is UIImagePickerControllerSourceTypePhotoLibrary.
#Arun
i am also face the same problem add global property in header file.
I hope the below code is useful for you
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
[imgPicker setDelegate:self];
[imgPicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[imgPicker setAllowsEditing:YES];
[imgPicker setModalPresentationStyle:UIModalPresentationCurrentContext];
UIPopoverController *popOver = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
popOver.delegate = self;
self.popoverImageViewController = popOver;
[self.popoverImageViewController presentPopoverFromRect:CGRectMake(0, 0, 160, 40) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
In that header file create global property like this
#property (strong) UIPopoverController *popoverImageViewController;
For Swift with iOS11:
videoEditor.modalPresentationStyle = .popover
self.present(picker, animated: true)
let popover = picker.popoverPresentationController
popover?.sourceView = self.view
// then config popover frame and arrow style here
I have a UIImagePickerController, and while it's loading, I want to display a disclaimer in a modalView.
- (void) viewDidLoad
{
self.picker = [[UIImagePickerController alloc] init];
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.picker.delegate = self;
[self presentModalViewController:self.picker animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
DisclaimerController* disclaimer = [[DisclaimerController alloc] init]; // Loads the Xib inside the init method
UINavigationController* controller = [[UINavigationController alloc] initWithRootViewController:disclaimer];
[self.navigationController presentModalViewController:controller animated:YES];
}
But it doesn't shows up.
And I don't want to dismiss the picker while the disclaimer is showing or show it later, because there are some treatments that takes some time and the time the user reads the disclaimer would prevent him to wait too long after closing the disclaimer.
I would solve it using an AlertView.
But if you prefer using your method maybe this will do the trick
Try this:
- (void) showModalDisclaimer {
DisclaimerController* disclaimer = [[DisclaimerController alloc] init];
// Loads the Xib inside the init method
UINavigationController* controller = [[UINavigationController alloc]
initWithRootViewController:disclaimer];
[self.picker presentModalViewController:controller animated:YES];
// notice self.picker
}
- (void) viewDidLoad
{
self.picker = [[UIImagePickerController alloc] init];
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.picker.delegate = self;
[self presentModalViewController:self.picker animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO
withAnimation:UIStatusBarAnimationNone];
[self performSelector:#selector(showModalDisclaimer) withObject:nil afterDelay:0.1];
}
I have a problem with my application. It crashes after few times of working with images and I have no idea why.
I have a TabBar, in one item of TabBat I have a navigation controller. In the root controller of that navigation I have a two buttons. One button is to get an image from camera or photo library, the second button is to get an image from saved images in the app. With selected image I go to next view controller (SelectImageViewController).
With the first button I use that code:
- (void) showImagePickerWithSourceType:(NSInteger) sourceType
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = sourceType;
picker.allowsEditing = NO;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *selectedImage = (UIImage *)[info objectForKey:#"UIImagePickerControllerEditedImage"];
if (selectedImage == nil)
selectedImage = (UIImage *)[info objectForKey:#"UIImagePickerControllerOriginalImage"];
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
SelectImageViewController *selectImageViewController = [[[SelectImageViewController alloc] initWithImage:selectedImage] autorelease];
[self.navigationController pushViewController:selectImageViewController animated:YES];
}
With the second button I use:
DocumentsViewController *documentsViewController = [[[DocumentsViewController alloc] init] autorelease];
[self.navigationController pushViewController:documentsViewController animated:YES];
DocumentsViewController is a TableViewController with list of images, when I select one image than I go to the SelectImageViewController.
In SelectImageViewController I make some image processing and then go to next view controller where I make another image processing.
Here is some code from SelectImageViewController:
- (id) initWithImage:(UIImage *) image
{
self = [super init];
if (!self) return nil;
self.originalImage = image;
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
[NSThread detachNewThreadSelector:#selector(processImage) toTarget:self withObject:nil];
}
- (void) processImage
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
self.originalImage = [ImageHelper scaleAndRotateImage:self.originalImage toSize:CGSizeMake(1500, 1500)];
self.processedImage = [ImageHelper scaleImage:self.originalImage maxWidth:320 maxHeight:367];
[self performSelectorOnMainThread:#selector(finish) withObject:nil waitUntilDone:NO];
[pool release];
}
- (void) finish
{
imageView = [[UIImageView alloc] initWithImage:self.processedImage];
imageView.center = self.view.center;
[self.view addSubview:imageView];
[self.view sendSubviewToBack:imageView];
[NSThread detachNewThreadSelector:#selector(processImage2) toTarget:self withObject:nil];
}
- (void) processImage2
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *corners = [OpenCV processImage:self.processedImage];
[self performSelectorOnMainThread:#selector(finish2) withObject:nil waitUntilDone:NO];
[pool release];
}
In the SelectImageViewController I have one button and when I click it I process the original image and then go to the next view controller.
In the last view controller in viewDidLoad method I process one more time the image.
I know that all method for image processing take a lot of memory and some time (especially that my original image which I use often is not scaled), but the application also crashes when I only select an image from photo library and go to SelectImageViewController. Maybe I shouldn't use a navigation controller? Has anybody an idea what can be wrong?
Thanks for any help.
Take care about the autorelease. Functions usually return autorelease objects. You are within an autorelease pool so, it is possible that the image wont exists when you call the last selector. Try assigning the images by using de setter method
[self setProcessedImage:[ImageHelper scaleImage:self.originalImage maxWidth:320 maxHeight:367]];
only if you have declared your variable as an instance property with retain or copy, it will retain the image.
Use NSZombieEnabled to see what happens. It seems to be a classic problem of a freed object.
I have a hierarchy of views:
compView with two children:
bgView
objectView.
I'm passing objectView to the cameraOverlayView property of the UIImagePickerController. Once the ImagePicker is done I update the image in the bgView and I would like to continue to display the view tree including the objectView which was passed to the UIImagePickerController as an overlayView.
The problem is that after calling dismissModalViewControllerAnimated to close the UIImagePickerController, the objectView is not appearing, as if the UIImagePickerContoller is hiding it. I checked in the debugger and it doesn't seem to be dealocated. The pointer is still valid. But the view is not showing.
Any ideas of what I might be doing wrong?
Thanks,
Eddy
Here a bit of code to show you what I'm doing:
From myViewController.m:
- (void)loadView {
CGRect rect = self.navigationController.view.bounds;
compView = [[UIView alloc] initWithFrame:rect];
bgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Storage/dummy_bg.png"]];
objectView = [[PropImageView alloc] initWithImage:[UIImage imageNamed:#"Storage/rasta.png"]];
[objectView setUserInteractionEnabled:YES];
[objectView setMultipleTouchEnabled:YES];
[compView addSubview:bgView];
[compView addSubview:objectView];
self.view = compView;
[self placeObject];
[objectView release];
[bgView release];
[compView release];
}
- (void) placeObject
{
NSLog(#"camera button pressed");
// make sure camera is avaialble before setting it as source
//
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
#if !TARGET_IPHONE_SIMULATOR
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
picker.allowsEditing = NO;
picker.view.hidden = NO;
picker.cameraOverlayView = objectView;
[self presentModalViewController:picker animated:NO];
[picker release];
#endif
}
// from PickImageAppDelegate.m
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
// Dismiss the image selection, hide the picker and
[picker dismissModalViewControllerAnimated:YES];
bgView.image = [self rotateImage:image byOrientationFlag:UIImageOrientationRight];
}
[picker dismissModalViewControllerAnimated:YES];
That should be
[self dismissModalViewControllerAnimated:YES];