如何使用动画关闭一堆模态视图控制器而不在屏幕上闪烁顶部和底部之间任何呈现的VC? [英] How to dismiss a stack of modal view controllers with animation without flashing on screen any of the presented VCs between the top and bottom?

查看:151
本文介绍了如何使用动画关闭一堆模态视图控制器而不在屏幕上闪烁顶部和底部之间任何呈现的VC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:通过下面的屏幕截图方法大纲修复。这有效但是有更优雅的方式吗?

UPDATED: Fixed via "screenshot" method outline below. This works but is there a more elegant way?

我如何解除一堆带有动画的模态视图控制器,而不会在屏幕上闪烁任何呈现的VC之间顶部和底部?尝试使用动画执行此操作无效。请参阅下面的代码和描述我的问题的内联注释。您可以将此代码复制/粘贴到Xcode中的新项目中,以便自己查看是否符合要求!

How would I go about dismissing a stack of modal view controllers with animation without flashing on screen any of the presented VCs between the top and bottom? Trying to do this with animation isn't working. See code below and inline comments describing my issue. You can copy/paste this code into a new project in Xcode to see for yourself if you'd like!

//
//  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's 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's 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's 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's 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, i.e. 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's 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's background color
    self.view.backgroundColor = [UIColor redColor]; // Color of self, root VC
}

@end

MyViewController.m(允许我们使用自定义dealloc方法进行调试)

MyViewController.m (enables us to have a custom 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

更新:
为dealloc调试添加了新的MyViewController.m文件。

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

有趣的是,日志看起来像这样:

Interestingly, the log comes out looking 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

更新:
我添加了一个示例项目所以如果您愿意,可以非常轻松地观察第一个句柄: https://github.com/johnerck/MultipleModals

另外,我已阅读多次从其他视图控制器呈现视图控制器。他们甚至说,例如,如果用户取消当前操作,您可以通过关闭第一个呈现的视图控制器来删除链中的所有对象。解除视图控制器不仅会解除视图控制器,还会解除它所呈现的任何视图控制器。 我看到这种行为,但动画总共显示3个视图,而不是预期的2。

Also, I have read Presenting View Controllers from Other View Controllers many times. They even say, "For example, if the user cancels the current operation, you can remove all objects in the chain by dismissing the first presented view controller. Dismissing a view controller dismisses not only that view controller but also any view controllers it presented." I am seeing this behavior but animation is displaying 3 views in total, not the expected 2.

推荐答案

这不是错误。仅当 dismissViewControllerAnimated 时,才会为 self.presentedViewController (purple)更改删除动画,但不能为所有嵌套的VC更改。当purple收到有关使用动画删除的消息时,它会删除所有 presentsViewController 而不显示动画。然后你会看到没有嵌套控制器的紫色动画。要检查这一点,您只需创建自己的VC类并检查-dealloc方法。

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

这篇关于如何使用动画关闭一堆模态视图控制器而不在屏幕上闪烁顶部和底部之间任何呈现的VC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆