How to remove a stack of modal view controllers with animation without blinking on the screen of any of the presented VCs between the top and bottom?

UPDATED: Fixed using the scheme of the screenshot method below. It works, but is there a more elegant way?

How can I discard a stack of modal view controllers with animations without blinking on the screen of any of the presented VCs between the top and bottom? Trying to do this using animation does not work. See the code below and inline comments describing my problem. You can copy / paste this code into a new project in Xcode to see this if you want!

// // ViewController.m // MultipleModals // #import "ViewController.h" #import "MyViewController.h" #import "MyHelper.h" @interface ViewController () @end @implementation ViewController static BOOL doAgain = YES; // So when red appears again, we don't endlessly cycle (for testing) - (void)viewDidAppear:(BOOL)animated { // Invoke super [super viewDidAppear:animated]; // Prevent loop when we dismiss all the way back to red (for testing) if (doAgain) { // Okay here where the demo code starts... // PRESENTING a full stack of modals WITHOUT animation WORKS and results in the user // only seeing orange when this red view controller "appears" (red never actually appears, which is great)... MyViewController *purple = [[MyViewController alloc] init]; purple.title = @"purple"; // For use in MyViewController dealloc method purple.view.backgroundColor = [UIColor purpleColor]; [self presentViewController:purple animated:NO completion:^{ // Purple successfully gets presented and the user never sees purple, great. NSLog(@"Purple?"); MyViewController *green = [[MyViewController alloc] init]; green.view.backgroundColor = [UIColor greenColor]; green.title = @"green"; // For use in MyViewController dealloc method [purple presentViewController:green animated:NO completion:^{ // Green successfully gets presented and the user never sees green, great. NSLog(@"Green?"); MyViewController *orange = [[MyViewController alloc] init]; orange.view.backgroundColor = [UIColor orangeColor]; orange.title = @"orange"; // For use in MyViewController dealloc method [green presentViewController:orange animated:NO completion:^{ // Orange successfully gets presented and the user DOES see orange, great. NSLog(@"Orange?"); // FIXED MY ISSUE STARTING HERE // Comment out the following code to toggle between // the "flashing purple issue" and "the desired outcome" (single // animation from top to bottom regardless of how many VCs are // on the stack, ie no flashing). // Get orange screenshot UIImage *orangeScreenShotImage = [MyHelper screenshot]; UIImageView *orangeScreenShotImageView = [[UIImageView alloc] initWithImage:orangeScreenShotImage]; // Give purple an orange screenshot since orange will just "flash away" and then purple will animate // away but we'll disguise purple to appear as if it orange by layering a screenshot of orange on purple. Boom. [purple.view addSubview:orangeScreenShotImageView]; // FIXED MY ISSUE ENDING HERE // FOR TESTING PURPOSES... dismiss after 5 seconds... dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ doAgain = NO; // Prevent viewDidAppear loop (related to my testing code)... // THIS IS MY BUG HERE. WHEN I WANT TO **ANIMATE** THE DISMISSAL OF ORANGE ALL THE WAY BACK TO RED, HOWEVER, I SEE PURPLE FOR A FLASH BEFORE RED!! WHY? // If I do not animate, things work as expected and I go from orange directly back to red in one flash. Why can't I go from orange back red WITH ANIMATION without seeing a flash of purple? BOOL animateDismissalOfOrangeBackToRed = YES; // YES causes me to see a flash of purple before red, why? [self dismissViewControllerAnimated:animateDismissalOfOrangeBackToRed completion:^{ NSLog(@"Back to red..."); }]; }); }]; }]; }]; } } - (void)viewDidLoad { // Invoke super [super viewDidLoad]; // Set self background color self.view.backgroundColor = [UIColor redColor]; // Color of self, root VC } @end 

MyViewController.m (allows us to have our own dealloc method for debugging)

 // // MyViewController.m // MultipleModals // #import "MyViewController.h" @interface MyViewController () @end @implementation MyViewController - (void)dealloc { NSLog(@"Inside dealloc self.title = %@", self.title); } @end 

UPDATED: Added a new file MyViewController.m for debugging dealloc.

Interestingly, the magazine looks like this:

 2014-11-20 10:06:28.847 MultipleModals[5470:946774] Purple? 2014-11-20 10:06:28.851 MultipleModals[5470:946774] Green? 2014-11-20 10:06:28.853 MultipleModals[5470:946774] Orange? 2014-11-20 10:07:04.055 MultipleModals[5470:946774] Inside dealloc self.title = orange 2014-11-20 10:07:04.056 MultipleModals[5470:946774] Inside dealloc self.title = green 2014-11-20 10:07:04.565 MultipleModals[5470:946774] Back to red... 2014-11-20 10:07:04.566 MultipleModals[5470:946774] Inside dealloc self.title = purple 

UPDATED: I added a sample project so that you can easily see this first descriptor if you want: https://github.com/johnerck/MultipleModals

In addition, I have repeatedly read the view controller view from other view controllers. They even say: β€œFor example, if the user cancels the current operation, you can delete all the objects in the chain by rejecting the first view controller that is presented. Rejecting the view controller rejects not only this view controller, but any view controllers that it has submitted.” I see this behavior, but the animation displays only 3 views, not the expected 2.

+5
source share
1 answer

It's not a mistake. You change the delete animation only for self.presentedViewController ("purple") when dismissViewControllerAnimated , but not for all nested VCs. When purple receives a delete message with animation, it deletes all presentedViewController without animation. And then you see a purple animation without nested controllers. To test this, you can simply create your own VC class and test the -dealloc method.

0
source

Source: https://habr.com/ru/post/982615/


All Articles