Warning message after actionSheet buttons are pressed - ios

I am very new to iOS development and have encountered an error that I just can't seem to find a solution for. I have searched for solutions everywhere, but maybe it is my newness that is preventing me from seeing the problem.
The exact warning that is printed in the log is:
Attempt to dismiss from view controller <_UIAlertShimPresentingViewController: 0x7aaa4b90> while a presentation or dismiss is in progress!
It occurs right after I touch a button on the actionSheet.
Here is the code:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
if (buttonIndex == 0) {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:nil];
}
else if (buttonIndex == 1) {
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:nil];
}
else if (buttonIndex == 2) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:picker animated:YES completion:nil];
}
} else {
if (buttonIndex == 0) {
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:NO completion:NULL];
}
else if (buttonIndex == 1) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:picker animated:YES completion:NULL];
}
}
}
The implementation of the actionSheet, I have the IBAction connected a toolbar button located an the .xib file.
- (IBAction)addImage:(id)sender {
UIActionSheet *popUpSheet = [[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles: nil];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[popUpSheet addButtonWithTitle:#"Camera"];
[popUpSheet addButtonWithTitle:#"Photo Library"];
[popUpSheet addButtonWithTitle:#"Camera Roll"];
[popUpSheet addButtonWithTitle:#"Cancel"];
popUpSheet.cancelButtonIndex = popUpSheet.numberOfButtons-1;
} else {
[popUpSheet addButtonWithTitle:#"Photo Library"];
[popUpSheet addButtonWithTitle:#"Camera Roll"];
[popUpSheet addButtonWithTitle:#"Cancel"];
popUpSheet.cancelButtonIndex = popUpSheet.numberOfButtons-1;
}
[popUpSheet showFromBarButtonItem: self.toolbarItems[0] animated:YES]; }
Everything has been delegated correctly from what I can tell:
DetailViewController.m
#interface DetailViewController () < UINavigationControllerDelegate, UIImagePickerControllerDelegate >
DetailViewController.h
#interface DetailViewController : UIViewController <UIActionSheetDelegate>
Any insight would be greatly appreciated and extremely helpful.

Your code looks correct. Try using the:
actionSheet:didDismissWithButtonIndex:
method. It's sent to the delegate after the animation ends. Hope it helps.

Finally figured out the problem. The compiler was giving me this warning because Apple recently combined UIActionsheet and UIAlert into one controller type called UIAlertController. Used the new UIAlertController and my problem was solved.
- (IBAction)addImage:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
UIAlertController *popUpSheet = [UIAlertController alertControllerWithTitle:nil message:#"Select your Choice" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *photoLibrary = [UIAlertAction actionWithTitle:#"Photo Library" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:nil];
NSLog(#"Photo Library was touched");
[popUpSheet dismissViewControllerAnimated:YES completion: nil];
}];
UIAlertAction *recentPhotos = [UIAlertAction actionWithTitle:#"Camera Roll" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:picker animated:YES completion:nil];
NSLog(#"Camera Roll was touched");
[popUpSheet dismissViewControllerAnimated:YES completion: nil];
}];
UIAlertAction *camera = [UIAlertAction actionWithTitle:#"Camera" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:nil];
NSLog(#"Camera was touched");
[popUpSheet dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[popUpSheet dismissViewControllerAnimated:YES completion:nil];
}];
[popUpSheet addAction:photoLibrary];
[popUpSheet addAction:recentPhotos];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[popUpSheet addAction:camera];
}
[popUpSheet addAction:cancel];
[self presentViewController:popUpSheet animated:YES completion:nil];
}

Related

Application terminating while clicking camera use image button objective c

My application terminates showing Message from debugger: Terminated due to signal 9 after doing rigorous searching didn't find any thing , i have also checked for memory leaks but does not find any..
Problem Statement - When i open camera from my app and after capturing image when i select use image my app terminates.
My Code
- (void)imagePickerController:(UIImagePickerController )picker didFinishPickingMediaWithInfo:(NSDictionary )info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil);
[picker dismissViewControllerAnimated:YES completion:NULL];
}
I used to select image from both camera and gallery using imagepicker with uialertactionsheet. This code is working for me, so you try this. And use these delegate's
- (IBAction)Camera_Click:(id)sender
{
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
// Photos from Gallery by calling Method
UIAlertAction *choose = [UIAlertAction actionWithTitle:#"Select from photos" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[self performSelector:#selector(choosePhotoFromGallery)];
[alertView dismissViewControllerAnimated:YES completion:nil ];
}];
//Take New Photo From Camara
UIAlertAction *Capture = [UIAlertAction actionWithTitle:#"Capture from camera" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[self performSelector:#selector(takePhotoFromCamara)];
[alertView dismissViewControllerAnimated:YES completion:nil ];
}];
UIAlertAction *Cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){
}];
//Adding the alertView Actions
[alertView addAction:choose];
[alertView addAction:Capture];
[alertView addAction:Cancel];
//Presents the AlertView
[self presentViewController:alertView animated:YES completion:nil];
}
- (void)takePhotoFromCamara
{
UIImagePickerController *Take_pic = [[UIImagePickerController alloc] init];
Take_pic.delegate = self;
Take_pic.allowsEditing = YES;
Take_pic.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:Take_pic animated:YES completion:NULL];
}
- (void)choosePhotoFromGallery
{
UIImagePickerController *Choose_picker = [[UIImagePickerController alloc] init];
Choose_picker.delegate = self;
Choose_picker.allowsEditing = YES;
Choose_picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:Choose_picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *imgPicker = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
self.your_imgView.image = imgPicker;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:NULL];
}
**Finally you add this two in your app info.plist file, otherwise app will crash.
<key>NSPhotoLibraryUsageDescription</key>
<string><$YourAppname$>We access your photo library.</string>
<key>NSCameraUsageDescription</key>
<string><$YourAppname$>We access your camera.</string>**

A_UIViewController presentViewController B_UIViewController presentViewController UIImagePickerController dismiss A_UIViewController

Code in A_UIViewController:
PrestBViewController *aviewcontroller = [[PrestBViewController alloc] init];
[self presentViewController:aviewcontroller animated:YES completion:nil];
Code in B_UIViewController:
-(void)presentAction {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = (id)self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:imagePickerController animated:YES completion:nil];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
When I run the code, it crashes at:
[picker.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Can anyone help?
Code in A_viewcontroller
- (IBAction)PresentAction:(id)sender {
B_ViewController *aviewcontroller = [self.storyboard instantiateViewControllerWithIdentifier:#"aa"];
[self presentViewController:aviewcontroller animated:YES completion:nil];
}
Code in B_viewController
#implementation ViewController{
UIImagePickerController *picker;
}
- (void)viewDidLoad {
[super viewDidLoad]; //Check if Camera Available
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Error" message:#"Device has no Camera" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:ok];
[self presentViewController:alertController animated:YES completion:nil];
}
- (IBAction)takePic:(id)sender { //Button to get image from camera
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
- (IBAction)chooosePic:(id)sender { //Button to get image from albums
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //Choose image
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { //if cancelled before selection
[picker dismissViewControllerAnimated:YES completion:NULL];
}
Works Fine Try

Cancel button not working in UIImagePickerView

I am use UIImagePickerView in my code in which three buttons are there. One to take photo, second to choose photo and third to cancel. The code as below:
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select the operation to proceed?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Take Photo", #"Select Photo", nil];
[actionSheet showInView:self.view];
When I click on the Cancel button it does not work.
I am using UIImagePickerViewDelegate method as below.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
#try {
//set selected image in imageview by imagepickerview
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
imgProfilePic.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:nil];
}
#catch (NSException *exception) {
NSLog(#"%#",exception.description);
}
}
//- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
//{
// NSLog(#"####");
// [picker dismissViewControllerAnimated:YES completion:NULL];
//}
Please check my code for UIImagePickerView and provide me guidance for correct code.
#pragma mark - Actionssheet delegate method for Image
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
#try {
if(buttonIndex != 3)
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
if(buttonIndex == 0)
{
NSLog(#"Choose Photo from Camera");
//simulator has no camera so app will crash, below call just provide the alert that device has no camera.
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Device has no camera"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[myAlertView show];
}
else
{
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
}
if(buttonIndex == 1)
{
NSLog(#"Choose Photo from Gallary");
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
// if (buttonIndex == 3)
// {
// NSLog(#"###");
// }
//
// else
// {
// NSLog(#"Cancel the tab");
// [picker dismissViewControllerAnimated:YES completion:NULL];
//
// }
[self presentViewController:picker animated:YES completion:nil];
}
}
#catch (NSException *exception) {
NSLog(#"%#",exception.description);
}
}
I think you are new for the stackOverflow and iOS application Development. That UIActionsheet and UIImagePickerController both are different things. So if you are create a actiohsheet like:
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select the operation to proceed?"delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil otherButtonTitles:#"Take Photo", #"Select Photo", nil];
[actionSheet showInView:self.view];
Now you can called its button method like following:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex==0)
{
// take photo selected
}
else if (buttonIndex==1)
{
// select photo selected
}
else
{
// cancel button selected
}
}
You can also use UIAlertController that is the replacement of UIAlert and UIActionSheet from iOS8 so you can use like following:
UIAlertController* AlertSheet = [UIAlertController alertControllerWithTitle:#"New ActionSheet" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"Action" style:UIAlertActionStyleDefault //
handler:^(UIAlertAction * action) {
NSLog(#"Action");
}];
[AlertSheet addAction:defaultAction];
UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
}];
[AlertSheet addAction:cancleAction];
[self presentViewController:AlertSheet animated:YES completion:nil];
You can try this code its work for me
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:nil // Must be "nil", otherwise a blank title area will appear above our two buttons
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* button0 = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
// UIAlertController will automatically dismiss the view
}];
UIAlertAction* button1 = [UIAlertAction
actionWithTitle:#"Take photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// The user tapped on "Take a photo"
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL]; }];
UIAlertAction* button2 = [UIAlertAction
actionWithTitle:#"Choose Existing"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// The user tapped on "Choose existing"
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}];
[alert addAction:button0];
[alert addAction:button1];
[alert addAction:button2];
[self presentViewController:alert animated:YES completion:nil];
UIActionSheet is deprecated since iSO 8. You should use UIAlertController
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:nil // Must be "nil", otherwise a blank title area will appear above our two buttons
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* button0 = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
// UIAlertController will automatically dismiss the view
}];
UIAlertAction* button1 = [UIAlertAction
actionWithTitle:#"Take photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// The user tapped on "Take a photo"
UIImagePickerController *imagePickerController= [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:^{}];
}];
UIAlertAction* button2 = [UIAlertAction
actionWithTitle:#"Select Photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// The user tapped on "Select Photo"
UIImagePickerController *imagePickerController= [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:^{}];
}];
[alert addAction:button0];
[alert addAction:button1];
[alert addAction:button2];
[self presentViewController:alert animated:YES completion:nil];

Ios uialertcontroller uiimagepicker dismiss : app crash

I have created a new app under xcode 6 and an old cold no more work.
Since iOS 8 we use UIalertcontroller to show action sheet
I use it to lauch photolibrary and select a picture but when I want to dismiss the picker, my app crash and I don't know why.
Below my code:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
UIAlertController * uiViewActionSheet= [UIAlertController
alertControllerWithTitle:#"Action"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* chooseExisting = [UIAlertAction
actionWithTitle:NSLocalizedString(#"CHOOSE_EXISTING",#"Choose Existing")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Do some thing here
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
[uiViewActionSheet dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
[uiViewActionSheet dismissViewControllerAnimated:YES completion:nil];
}];
[uiViewActionSheet addAction:chooseExisting];
[uiViewActionSheet addAction:cancel];
[self presentViewController:uiViewActionSheet animated:YES completion:nil];
Below the imagepicker function :
(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.uImageProfile.image = chosenImage;
self.lstatutImage.text = #"save";
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
if(picker.sourceType == UIImagePickerControllerSourceTypeCamera)
{
UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil);
}
__block NSString* resultSaveImage = #"";
//Save image onthe server
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
resultSaveImage = [controllerObject saveProfileImage:self.uImageProfile.image];
dispatch_async(dispatch_get_main_queue(), ^{
if(![resultSaveImage isEqualToString:#"\"ok\""])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"ERROR",#"Error") message:resultSaveImage delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
});
});
}
My code crash here :
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Have you any idea ?
You're dismissing the picker, and then calling it:
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
if(picker.sourceType == UIImagePickerControllerSourceTypeCamera) {...
You also don't need the [uiViewActionSheet dismissViewControllerAnimated:YES completion:nil]; lines!
Try moving the dismiss line to the end. If it still crashes, it might be that the presentingViewController is not alive anymore.

UIImagePickerController not presenting in iOS 8

Is anyone else having an issue with UIImagePickerController in iOS 8? The method below works perfectly well in iOS 7 on an iPad, but I get the following error when I run this in XCode 6 (Beta 3 or 4) when I try to present the picker (last line). If it matters, the selection of the sourceType is coming from an alertView that is presented in the same place.
Warning: Attempt to present <UIImagePickerController: 0x7c0ae400> on <CAGUCreateContactViewController: 0x7bf61a00> which is already presenting (null)
Method to open imagePicker.
- (void)openPhotoPicker:(UIImagePickerControllerSourceType)sourceType
{
if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {
NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
if ([availableMediaTypes containsObject:(NSString *)kUTTypeImage]) {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
imagePickerController.sourceType = sourceType;
imagePickerController.mediaTypes = #[(NSString *)kUTTypeImage];
imagePickerController.delegate = self;
self.imagePickerController = imagePickerController;
if (sourceType == UIImagePickerControllerSourceTypeCamera) {
[self presentViewController:self.imagePickerController animated:YES completion:nil];
} else {
if (self.popoverVC) {
[self.popoverVC dismissPopoverAnimated:YES];
self.popoverVC = nil;
}
self.popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[self.popoverVC presentPopoverFromRect:self.nameAndPicCell.picture.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
}
}
I think this is because in iOS 8, alert views and action sheets are actually presented view controllers (UIAlertController). So, if you're presenting a new view controller in response to an action from the UIAlertView, it's being presented while the UIAlertController is being dismissed. I worked around this by delaying the presentation of the UIImagePickerController until the next iteration of the runloop, by doing this:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self openPhotoPicker:sourceType];
}];
However, the proper way to fix this is to use the new UIAlertController API on iOS 8 (i.e. use if ([UIAlertController class]) ... to test for it). This is just a workaround if you can't use the new API yet.
I agree with Ben Lings issue detection. I would suggest a simpler solution in case when using UIActionSheet. I simply moved my code that reacts on Action Sheet selection from:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
{
// my code
}
into:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation
{
// my code
}
This way app is guarantied that code will be executed AFTER UIActionSheet animation finishes.
Since UIAlertView has similar delegate method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation
{
// my code
}
I suppose that similar solution may apply.
Here is a solution that worked for me
if([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self presentViewController:cameraUI animated:NO completion:nil];
}];
}
else{
[controller presentViewController:cameraUI animated:NO completion:nil];
}
Remember to alloc cameraUI
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
Build and Go!
I was facing the same problem in iOS 8.
Then I saw the change log of the latest update to iOS i.e. 8.0.2 on the device.
It is mentioned in this update that_
"Fixes an issue that prevented some apps from accessing photos from Photo Library"
So test your app using XCode 6 on device with iOS 8.0.2 version it will work fine
Don't test it on iOS 8.0 simulator.
This helped me, hope the same for you.
UIImagePickerController *imagePickerController= [[UIImagePickerController alloc] init];
[imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
// image picker needs a delegate so we can respond to its messages
[imagePickerController setDelegate:self];
self.shouldCallViewWillAppear = NO;
if(IS_IOS8)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Place image picker on the screen
[self presentViewController:imagePickerController animated:YES completion:nil];
}];
}
else
{
[self presentViewController:imagePickerController animated:YES completion:nil];
}
You can dismiss the presented view controller (if any) by using
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
This worked for me.
All you need to do is dismiss already presented ViewController:
if (self.presentedViewController) {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
[self openPhotoPicker:sourceType];
If it still produces error, put openPhotoPicker: to completion handler
I simply did this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,
(unsigned long)NULL), ^(void) {
[self retractActivePopover];
dispatch_async(dispatch_get_main_queue(), ^ {
_activePopover=imagePickerPopover;
UIBarButtonItem *callingButton = (UIBarButtonItem*) sender;
[imagePickerPopover presentPopoverFromBarButtonItem:callingButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
});
});
On iOS 8 you should use the new API:
if (SYSTEM_VERSION_IOS_8) {
self.imagePickerController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = self.imagePickerController.popoverPresentationController;
popPC.barButtonItem = self.popoverItem;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:self.imagePickerController animated:YES completion:nil]
}
I recommend you watch the 2014 WWDC session 228 a look in side presentation controllers
I went through a lot of pain coming up with a solution which works on both iPad and iPhone, this is the final code which some of it comes from comments of other people:
the code has some bugs but it's a very good place to start :)
definitions :
__weak IBOutlet UIButton *attachButton;
UIImage *image;
button's action :
- (IBAction)doAttach:(id)sender {
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:#"Select image from" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"From library",#"From camera", nil] ;
[action showInView:self.view];
}
#pragma mark - ActionSheet delegates
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if( buttonIndex == 1 ) {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusAuthorized)
{
NSLog(#"%#", #"You have camera access");
}
else if(authStatus == AVAuthorizationStatusDenied)
{
NSLog(#"%#", #"Denied camera access");
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){
NSLog(#"Granted access to %#", AVMediaTypeVideo);
} else {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#“no camera access“
message: #“if you need to use camera in this application go to settings -> appName -> and turn on camera.”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
NSLog(#"Not granted access to %#", AVMediaTypeVideo);
return ;
}
}];
}
else if(authStatus == AVAuthorizationStatusRestricted)
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#“no camera access“
message: #“if you need to use camera in this application go to settings -> appName -> and turn on camera.”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
NSLog(#"%#", #"Restricted, normally won't happen");
}
else if(authStatus == AVAuthorizationStatusNotDetermined)
{
NSLog(#"%#", #"Camera access not determined. Ask for permission.");
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){
NSLog(#"Granted access to %#", AVMediaTypeVideo);
} else {
NSLog(#"Not granted access to %#", AVMediaTypeVideo);
return ;
}
}];
}
else
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#“No camera access“
message: #“error accusing camera”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
return;
//NSLog(#"%#", #"Camera access unknown error.");
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *pickerView =[[UIImagePickerController alloc]init];
pickerView.allowsEditing = YES;
pickerView.delegate = self;
pickerView.sourceType = UIImagePickerControllerSourceTypeCamera;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ];
pickerView.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = pickerView.popoverPresentationController;
popPC.sourceView = attachButton;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:pickerView animated:YES completion:nil];
} else {
[self presentModalViewController:pickerView animated:YES ];
}
}
}else if( buttonIndex == 0 ) {
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#“no access to library”
message: #“if you wish to access photos in this app go to settings -> appName-> and turn on photos .”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
break;
default:
{
UIImagePickerController *pickerView = [[UIImagePickerController alloc] init];
pickerView.allowsEditing = YES;
pickerView.delegate = self;
[pickerView setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ];
pickerView.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popup = pickerView.popoverPresentationController;
popup.sourceView = attachButton;
popup.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:pickerView animated:YES completion:nil];
} else {
[self presentModalViewController:pickerView animated:YES ];
}
}
break;
}
}
}
#pragma mark - PickerDelegates
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
[self dismissModalViewControllerAnimated:true];
UIImage * img = [info valueForKey:UIImagePickerControllerEditedImage];
image = img;
}
performSelector:withObject:afterDelay solved my problem.
also didDismissWithButtonIndex do the trick.
Max
Here's a Xamarin solution. What worked for me was to add my actions to a Dismissed event handler.
this.btnPhoto.TouchUpInside += (sender, e) =>
{
actionSheet = new UIActionSheet ("Add Photo");
actionSheet.AddButton ("Take Photo");
actionSheet.AddButton ("Select from Library");
actionSheet.AddButton ("Cancel");
actionSheet.DestructiveButtonIndex = -1; // red
actionSheet.CancelButtonIndex = 3; // black
actionSheet.Clicked += delegate(object a, UIButtonEventArgs b)
{
actionSheet.Dismissed += (object aSender, UIButtonEventArgs dismissArgs) =>
{
switch (dismissArgs.ButtonIndex)
{
case 0:
showCamera ();
break;
case 1:
showPhotoLibrary ();
break;
}
};
};
actionSheet.ShowInView (view);
};

Resources