7

When I call dismissViewControllerAnimated:completion: to dismiss a UIViewController the completion block is never executed when the corresponding view is in the middle of being animated onto the screen (using presentViewController:animated:completion:).

The UIViewController does not even dissappear. It is like dismissViewControllerAnimated:completion: is being ignored.

The following code is a simplified code example because the original is much bigger. The code I have given below simulates a use-case where a network communication error might trigger a view to popup whilst another view is also being popped-up at the same time..

Code example:

NSLog(@"Presenting view");

[self presentViewController:changeLocationViewController animated:YES completion:^{
    NSLog(@"View done presenting");
}];

NSLog(@"Dismissing view");

[self dismissViewControllerAnimated:NO completion:^{
    NSLog(@"View done dismissing");
}];

Log output is:

2013-08-28 16:14:12.162 [1708:c07] Presenting view
2013-08-28 16:14:12.178 [1708:c07] Dismissing view
2013-08-28 16:14:12.583 [1708:c07] View done presenting


Does anyone know how to dismiss the UIViewController in these circumstances?

Thanks in advance.

4

3 回答 3

5

The reason this code snippet isn't working is because the completion block in these methods are executed at a later time after the animations have completed. You can see this in your logs: "Dismissing view" happens before "View done presenting". Try this instead:

NSLog(@"Presenting view");

[self presentViewController:changeLocationViewController animated:YES completion:^{
    NSLog(@"View done presenting");
    NSLog(@"Dismissing view");

    [self dismissViewControllerAnimated:NO completion:^{
        NSLog(@"View done dismissing");
    }];
}];

EDIT:

If you need to make sure the view is dismissed when the network error happens, try setting a boolean instance variable called networkErrorFound.

When you finish the network connection, set this to YES if an error happens. Then use this code:

[self presentViewController:changeLocationViewController animated:YES completion:^{
    NSLog(@"View done presenting");
    NSLog(@"Dismissing view");

    if (self.networkErrorFound) {
        [self dismissViewControllerAnimated:NO completion:^{
            NSLog(@"View done dismissing");
        }];
    }
}];

That way, it'll wait until it's done presenting to dismiss. You would also need to handle the case that the error happens after the animation is done (for instance, a slow connection that eventually fails), but that's outside the scope of this question.

于 2013-08-28T14:23:16.847 回答
1

Why dont you dismiss it when its done loading?

[self presentViewController:changeLocationViewController animated:YES completion:^{
    NSLog(@"View done presenting");

    NSLog(@"Dismissing view");

    [self dismissViewControllerAnimated:NO completion:^{
        NSLog(@"View done dismissing");
     }];
}];
于 2013-08-28T14:23:23.167 回答
0

OK. It seems like you want to present a VC, but if there is no network found, close the VC. The only reason that I can think of needing to do it this way is if the network only gets checked in the new VC that you are presenting (and want to dismiss if it fails to connect).

And you would be able to achieve that by implementing the code shown in the answer given by @aopsfan.

But think about that UI flow. You are telling a starving man (the user) he can have a sandwich (the next VC that he wants to see)... But WAIT! (dismiss the wanted VC) No, you can't have the sandwich (no network)! Fooled you!.

The way to do it to keep the UI flow nice and not aggravating, would be to check for network connection before presenting the VC. Probably check for network in the IBAction (?) that you use to present the new VC. That way, you can check before presenting. Instead of present-cancel

Heck, you could even show an HUD "in progress" View to let the user know what happening!

于 2013-08-28T14:58:23.630 回答