Problem opening new ViewController after UIImagePi

2020-04-19 08:08发布

问题:

I am trying to open up a new view (UnprocessedPhotoViewController) immediately after the delegate function for my UIImagePickerController returns a "didFinishPickingImage".

Unfortunately, it appears that I can either open the UIImagePickerController modal view, or switch to the UnprocessedPhotoViewController as a modal, but not both sequentially.

In the code below, a button press activates the pickPhoto IBAction. This code activates the UIImagePickerController successfully. After the user selects an image, the didFinishPickingImage delegate function is called, which stores the image to a variable, attempts to close the UIImagePickerController modal and open the UnprocessedPhotoViewController in a new modal.

Note: If I comment out the ImagePicker and run "showPhoto" directly, the UnprocessedPhotoViewController shows successfully. Also, if I make a new button to launch either view it works successfully, but I am unable to launch the views sequentially. I would expect that after a user selected the image, the new view would be launched which would allow the user to process the image.

What is the correct way to guarantee that the ImagePicker modal closes and then to open the UnprocessedPhotoViewController?

Thanks!!!

Code:

- (IBAction)pickPhoto:(id)sender{

//TODO: To be replaced with the gallery control launching code

// Load Image Selection Code    
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:self.imgPicker animated:YES];

}



// Dummy function assumes you either picked (or took a picture =D) of Angie and moves you right to the unprocessed viewing screen.
- (void) showPhoto{

// Start new view controller
[self dismissModalViewControllerAnimated:YES];
UnprocessedPhotoViewController *upViewController = [[UnprocessedPhotoViewController alloc] initWithNibName:@"UnprocessedPhotoViewController" bundle:nil];
upViewController.imageView.image = selectedImage;
upViewController.delegate = self;
upViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:[upViewController animated:YES]];
[upViewController release];

}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img {
selectedImage = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
[self dismissModalViewControllerAnimated:YES];

[self showPhoto];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}

回答1:

Implement viewDidAppear in your root view controller and based on member data decide to call showPhoto or not. The following example simply re-presents the UIImagePicker but any new modal view will work. viewDidAppear is called any time your root view controller’s view appears so you have to make sure the context is known when it is called. But it is the deterministic way to know that the modal view controller is gone.

- (IBAction) showPicker: (id) sender
{
    UIImagePickerController* picker = [[[UIImagePickerController alloc] init] autorelease];
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    picker.delegate = self;
    picker.allowsEditing = YES;

    [self presentModalViewController:picker animated:YES];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    imageChosen = YES;

    [self dismissModalViewControllerAnimated:YES];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    imageChosen = NO;

    [self dismissModalViewControllerAnimated:YES];
}

- (void) viewDidAppear: (BOOL) animated
{
    if ( imageChosen )
    {
        [self showPicker: self];
    }
}


回答2:

Another way to do this is to wrap the built-in dismissal animation with your own animation, and then catch the animationDidStop "event." This creates a composite animation, so when the built-in animation is done, your (empty) wrapper animation finishes you and alerts you that you're done.

This is slightly cleaner than the other answer here, IMO, as you don't need to keep a state variable or override viewDidAppear: (in my app, the view controller presenting the picker is quite a few objects removed from the utility code that handles picker management, and that would mean any view controller using my shared utility would have to override viewDidAppear:, or else fail to work):

-(void)dismissalAnimationDone:(NSString*)animationID 
                     finished:(BOOL)finished context:(void*)context
{
    UIImage* image = (UIImage*) context;
    // present controllers as you please
}

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
    [UIView beginAnimations:@"dismissal wrapper" context:image];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(dismissalAnimationDone:finished:context:)];

    [self.delegate dismissModalViewControllerAnimated:YES];

    [UIView commitAnimations];
}