简体   繁体   中英

dismissModalViewControllerAnimated nonatomic?

I have a weird timing issue, it seems. I open a uiimagepicker as a modal view. When the user picks an image or I want to take the image, save it to a variable, then open an email interface as a modalview.

My problem is that I am calling dismissModalViewController on the imagepicker, then calling presentmodalviewcontroller for my email interface, but the imagepicker isn't going away in time for the email view to be presented. Is there a way to 'wait' for that line of code to complete?

(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
  if( [[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@"public.image"] ){
    [self dismissModalViewControllerAnimated:YES];
    imageFromCamera = [[UIImageView alloc] initWithImage:[info objectForKey:UIImagePickerControllerOriginalImage]];

  MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc] init];
  mailView.mailComposeDelegate = self;
  [self presentModalViewController:mailView animated:YES];
  [mailView release];

}   
}

I'm pretty sure I've designed something wrong, but help me out if you can.

You can use performSelector:withObject:withDelay: to wait for a given time to pass (create another method that has the code to do later.

However, this can introduce lots of subtle timing bugs, so I'd suggest using it for only the most extreme of cases.

I think you could probably do something with viewDidAppear: look for a flag that you've set in didFinishPicking… indicating that you're waiting for the imagePicker's animation to end. Since it's didAppear, the animations should be done by then.

I've encountered a similar issue with dismissModalViewController and it has been driving me nuts. The only way I've been able to deal with it is by doing something like this, which is similar to what was suggested above. I don't like this solution but I haven't been able to figure out how to avoid it.

if ([self retainCount] == 1) 
  [self dismissModalViewControllerAnimated:YES];                    
else {
  [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
}

- (void)onTimer:(NSTimer*)theTimer {
    [self dismissModalViewControllerAnimated:YES];
    [theTimer invalidate];
}

The problem I noticed is that here is a timing issue surrounding when some object releases its hold on the modal view controller. And if I call dismissModalViewController when the retainCount is still 2 then the call just fails...nothing happens. But if I wait a second, the retain count always drops down to 1 and then the call to dismissModalViewController succeeds.

While the transition is happening, all views reside on an intermediate view (of type UITransitionView ). So just pick some outlet of which you know that it is a direct subview of the main window and check whether !([[outlet superview] isKindOfClass:[UIWindow class]]) and delay the execution using performSelector:withObject:withDelay: , pass all the relevant information to call the same method you're in and simply return.

As soon as the transition is finished, the condition will not be met anymore and the new animation can happen. This method is not prone to the timing complexities which can happen if you just call performSelector:withObject:withDelay: once.

I used this just recently and it works very well (I just happened to have an outlet to the main window which makes this even simpler):

//Called after [initialRootViewController dismissModalViewControllerAnimated:YES]
- (void)showTable {
    if([initialRootViewController.view superview] != window) {
        //View is still animating
        [self performSelector:@selector(showTable) withObject:nil afterDelay:0.1];
        return;
    }
    self.nibContents = [[NSBundle mainBundle] loadNibNamed:@"MainView" owner:self options:nil];
    [UIView transitionFromView:initialRootViewController.view toView:rootViewController.view duration:0.3 options:UIViewAnimationOptionTransitionCurlUp|UIViewAnimationOptionBeginFromCurrentState completion:^(BOOL finished){
        self.initialRootViewController = nil;
    }];
}

I am having a similar issue and believe it is a design issue. I would suggest instead of doing:

root vc presents image vc
root vc dismisses image vc
[simultaneous dismiss and present cause problems here]
root vc presents email vc
root vc dismisses email vc

You do:

root vc presents image vc
image vc presents email vc
root vc dismisses the vc stack

Keep in mind that dismissModalViewController can dismiss a whole stack of controllers to get to the caller. See the documentation for UIViewController .

vc = View Controller

I am using an image picker and dismissModalViewControllerAnimated is undoing one of my objects. I found that I have to save and restore my value.

This is what worked for me (Group and BigBlockViewController are my classes):

Group *workAround = bigBlockViewController.selectedGroup;
[picker dismissModalViewControllerAnimated:YES];
bigBlockViewController.selectedGroup = workaround;

My photo picker is performed from a flipsideViewController

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM