Understanding how to dismiss a UIImagePickerController - ios

I'm a bit confused, this isn't a question on how to dismiss a UIImagePickerController, it's more of a "why did that work" type of question. I am working in iOS7.
Looking online at the apple documentation (this link: https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/CameraAndPhotoLib_TopicsForIOS/Articles/TakingPicturesAndMovies.html#//apple_ref/doc/uid/TP40010406-SW6), I came across the following code for dismissing a UIImagePickerController:
[[picker parentViewController] dismissModalViewControllerAnimated: YES];
Edit: I know that that method was deprecated, so instead I tried the following, and that did not work either:
[[picker parentViewController] dismissViewControllerAnimated:YES completion:NULL];
Those didn't work for me. This however did work:
[picker dismissViewControllerAnimated:YES completion:NULL];
Is the apple documentation wrong? or just outdated?
Why does the second bit of code work, because from my understanding, its the parent view controllers job to dismiss something like a popover or in this case a UIImagePickerController
Thank you.
Edit: This is how I am presenting the UIImagePickerController, the UITapGestureRecognizer calls the first method which then calls the second.
- (IBAction)captureMoment:(UITapGestureRecognizer *)sender {
[self startCameraCaptureFromViewController:self usingDelegate:self];
}
- (BOOL)startCameraCaptureFromViewController:(UIViewController *)controller
usingDelegate:(id <UIImagePickerControllerDelegate, UINavigationControllerDelegate>)delegate {
if (delegate == nil || controller == nil || [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == NO) {
return NO;
}
UIImagePickerController *camera = [[UIImagePickerController alloc] init];
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
camera.allowsEditing = NO;
camera.delegate = delegate;
[controller presentViewController:camera animated:YES completion:NULL];
return YES;
}

There are 2 methods that worked for me
Use picker.presentingViewController instead of picker.parentViewController, answer by rmaddy
Use the following code in the imagePickerControllerDidCancel:, [picker dismissViewControllerAnimated:YES completion:NULL];
Here is the code in its entirety, this is placed in the UIViewController that presents the UIImagePickerController:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
}

The method dismissModalViewControllerAnimated has been deprecated since iOS6. The new method you are using is the correct one.

Related

Dismissing the image picker from the didFinishPickingMediaWithInfo method now impossible?

This seems like a simple question and I've seen similar ones answered but the answers just don't work (at least anymore). I have the following code in viewDidAppear:
UIImagePickerController *imagePicker;
imagePicker =[[UIImagePickerController alloc] init];
imagePicker.allowsEditing = YES;
{imagePicker.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;}
imagePicker.delegate=self;
NSLog(#"ViewDidAppear");
[self presentModalViewController:imagePicker animated:YES];
NSLog (#"Modal Window Displayed.");}
This allows the user to select an image from the image library, which works. Once that image is picked, didFinishPickingMediaWithInfo gets called which has this code at the top of it:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
NSLog(#"Image Is Picked");
[[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
[self dismissModalViewControllerAnimated:YES];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popViewControllerAnimated:YES];
As you can see, I've tried several different ways found here on StackOverflow to get this to work. They all get ignored. No errors, just nothing happens; the picker view never goes away. What gives? I'm using xCode 7.2.1.
I have a similar place in my code where I present another modal view and also can't get rid of it.
The problem is that the didFinishPickingMediaWithInfo method doesn't actually dismiss the other view until it is DONE with it's execution (even if what's running in that method takes almost a minute!). By the time that method was done, I had already presented another viewcontroller modally. Almost all of the techniques I'd been trying all along actually still work.
If you present with presentViewController instead of presentModalViewController:
[self presentViewController:imagePicker animated: YES];
then
[self dismissViewControllerAnimated:YES completion:nil];
should work - perhaps the combination of different functions you are calling all at once is confusing things.
If this doesn't work, perhaps try presenting it with a slight delay with dispatch_after - it could be that presenting it within viewDidAppear is causing the issue:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
[self presentViewController:imagePicker animated: YES];
}
Below code works for me perfectly. Hope it helps.
in class.h
#interface class : UIViewController<UIImagePickerControllerDelegate>
{
UIImagePickerController *picker;
}
in class.m when getPhoto called, PickerViewController presented.
- (IBAction)getPhoto:(UIButton *)sender {
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker2 didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker2 dismissViewControllerAnimated:YES completion:nil];
}
Globally declare your imagePicker like below
#implementation ViewController{
UIImagePickerController *imagePicker;
}
Display your image picker declared globally
- (IBAction)chooosePic:(id)sender {
imagePicker =[[UIImagePickerController alloc] init];
imagePicker.allowsEditing = YES; {imagePicker.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;}
imagePicker.delegate=self;
NSLog(#"ViewDidAppear");
[self presentModalViewController:imagePicker animated:YES];
NSLog (#"Modal Window Displayed.");
}
didFinishPickingMediaWithInfo method update as below:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[imagePicker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
Will Work

Removing UIImagePickerController from UINavigationController in a UIPopoverController

This worked in iOS6, so not sure what the issue is.
inside my UINavigationController (ioNavController) I present the UIImagePickerController with the Following:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.modalInPopover = YES;
imagePicker.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:imagePicker animated:NO completion:^{ }];
in my UIImagePickerControllerDelegate (which does get called)I have the Following:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
//This does not work
[ioNavController dismissViewControllerAnimated:YES completion:^{ /* Cleanup if Needed */ }];
//This does not work
[[picker parentViewController] dismissViewControllerAnimated:YES completion:^{ /* Cleanup if Needed */ }];
//This does not work
[picker removeFromParentViewController];
// This presents a new view on the Nav Controller. It shows the new view ontop of the ImagePicker. Image Picker View does not repond to touches.
[ioNavController pageToSelect:0];
}
Your delegate it's in the same controller that called the imagepicker? The same controller that called presentViewController should call the line below, and the imagepicker will be removed correctly.
[self dismissViewControllerAnimated:YES completion:nil]; //self here it's the same reference that called presentViewController
let me know if worked or helped.
The UIImagePickerController will remove itself when you use this code:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)pPicker {
[pPicker dismissViewControllerAnimated:YES completition:NULL]; }

Simple view controller switch causes: Attempt to present while a presentation is in progress

I am learning how to handle view controller hierarchies using the storyboard. I have 2 ViewControllers: the root of type cwViewController (what I understand is 'self' below) and a second of type WorkspaceViewController. I am getting "Attempt to present while a presentation is in progress!" as a result of this code.
- (IBAction)nextView {
WorkspaceViewController *workspace = [[WorkspaceViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:workspace animated:YES completion:NULL]; }
The answer to How to present view controller properly? is the closest answer that could apply but doesn't quite fit this scenario because I'm not switching back and forth between VCs, I'm just presenting one, then dismissing it to display the original.
Then, I tried dismissing the current one before presenting the second, as some answers suggested, like this:
[self dismissViewControllerAnimated:NO completion:nil];
[self presentViewController:workspace animated:YES completion:NULL];
But that just gets me an additional Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!
Doing some other research I saw similar problems were solved by adding a block to
[self dismissViewControllerAnimated:YES...]
But that doesn't help here because my warning occurs before I even get to a point where I call that dismiss method. Any further knowledge on how the order and hierarchy of views are meant to be handled would be a big help. Thanks very much.
Did you create a segue from the button to your WorkSpaceViewController? If so, you are likely attempting to present the WorkSpaceView twice - once when the button is selected and once from cwViewController. To eliminate the error, delete the segue from the button to WorkSpaceViewController and then recreate the segue - this time between cwViewController and the WorkSpaceViewController. That should take care of it.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// TODO: make this all threaded?
// crop the image to the bounds provided
img = [info objectForKey:UIImagePickerControllerOriginalImage];
NSLog(#"orig image size: %#", [[NSValue valueWithCGSize:img.size] description]);
// save the image, only if it's a newly taken image:
if ([picker sourceType] == UIImagePickerControllerSourceTypeCamera) {
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
}
// self.image_View.image = img;
// self.image_View.contentMode = UIViewContentModeScaleAspectFit;
NSLog(#"Picker has returned");
[self dismissViewControllerAnimated:YES
completion:^{
ModalViewController *sampleView = [[ModalViewController alloc] init];
[self presentModalViewController:sampleView animated:YES];
}];
}
try
[self presentModalViewController:workspace animated:YES];
if (![[self modalViewController] isBeingPresented]) {
[self dismissModalViewControllerAnimated:YES];
}

Instance method '-presentViewController:animated' not found

I'm fairly new to this, so bear with me. I have 2 errors left to fix in my code. In both cases my instance methods are not found:
-(IBAction)goFlipSide {
NSLog(#"goFlipSide has been called:");
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES];
[controller release];
}
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller {
[self dismissViewControllerAnimated:YES];
//This method gets fired when the user clicks done on the modal FlipsideViewController. This is different
//than the viewWillAppear.
self.navigationController.navigationBarHidden = TRUE;
/*
if (self.goViewSuccess == TRUE) {
//if the goViewSuccess boolean is set to YES - then we can load the load the goViewController
NSLog(#"goViewSuccess is YES");
[self loadGoViewController];
}
*/
}
Both instance methods not found are: presentViewController: and dismissViewControllerAnimated:.
What class is self? Those methods are only found on UIViewController. The full selectors are:
presentViewController:animated:completion:
dismissViewControllerAnimated:completion:
Try adding the completion block argument.
The code is supposed to be this
[self dismissViewControllerAnimated:YES completion:nil];
or if you want something when its done,
[self dismissViewControllerAnimated:YES completion:^{
//do stuff
}];
And for the other one
[self presentViewController:controller animated:YES completion:nil];

presentViewController doesnt "see" my viewControllers

MainMenuViewController presents BonusViewController modally. I want to Dismiss BonusViewController then display a new BonusViewController, effectively "resetting" BonusViewController.
Im using notifications to call this method in MainMenuViewController
-(void)resetBonus{
[self dismissViewControllerAnimated:YES completion:nil];
[self presentViewController: BonusViewController animated:NO completion:nil];
}
I expected BonusViewController to be auto-detected as I was typing it in the presentViewController call above but it was not and none of my viewControllers show up as I type which Im assuming means im doing this all wrong. Do I have to initialize the VC or allocate it before I can present it like this? Or can I even do this at all since im using storyboards?
I also tried this though I believe this method is deprecated
-(void)resetBonus{
[self dismissModalViewControllerAnimated:YES];
[self presentModalViewController: BonusViewController animated:NO ];
}
Did what Sumanth suggested but I get this message now:
so now I m doing :
#import "BonusViewController.h
....
-(void)resetBonus
{
BonusViewController *bonus = [[BonusViewController alloc]init];
[self dismissModalViewControllerAnimated:NO];
[self presentModalViewController: bonus animated:NO ];
}
the errors are all gone but when BonusViewController is presented the display is solid black, i can hear the sounds going but cant see anything on the screen
you should allocate and initialize the viewcontroller and present that using presentModalViewController write like this
BonusViewController *bonus = [[BonusViewController alloc]init];
[self dismissModalViewControllerAnimated:YES];
[self presentModalViewController: bonus animated:NO ];
Also dont forget to write #import "BonusViewController.h" in .h file
BonusViewController *objBonus = [[BonusViewController alloc]init];
[self dismissViewControllerAnimated:YES completion:NULL];
[self presentViewController:objBonus animated:YES completion:NULL];
You need to create and object of the viewcontroller and you are directly passing the viewcontroller which is not possible
#import "BonusViewController.h"
-(void)resetBonus
{
BonusViewController *BonusViewController = [[BonusViewController alloc]init];
[self dismissViewControllerAnimated:NO completion:nil];
[self presentViewController: BonusViewController animated:NO completion:nil];
}
Set Both of animated is NO
EDIT : #import "BonusViewController.h"
Im sure the answers given were correct but I could not get them to work properly. For some reason BonusViewController seems to be displayed as I can hear the sounds going but the screen is black and nothing is displayed visually.
I ended up doing the below for now in the intrest of time but this isnt the smooth effect I was really going for.
I have to re-visit this when I have more time to figure out a better way to do it.
-(void)endBonus
{
[self dismissViewControllerAnimated:NO completion:^{
[self performSelector:#selector(resetBonus) withObject:nil afterDelay:1];
}];
}
-(void)resetBonus
{
[self performSegueWithIdentifier: #"segueToBonus" sender: self];
}

Resources