关闭两个模态视图控制器

Posted

技术标签:

【中文标题】关闭两个模态视图控制器【英文标题】:Dismissing two modal view controllers 【发布时间】:2013-08-29 03:08:25 【问题描述】:

我发现了几个关于此的问题,但答案并没有解决我的问题。

我有两个使用 presentModalViewController 呈现的控制器。

我在主控制器调用的第一个控制器中添加了 modalTransitionStyle。第一个控制器正常呈现第二个控制器(没有过渡样式)。

FirstVC *first = [[FirstVC alloc] initWithNibName:@"FirstVC" bundle:nil];
first.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:first animated:YES];

SecondVC *second = [[SecondVC alloc] initWithNibName:@"SecondVC" bundle:nil];
[self presentModalViewController:second animated:YES];

这是我以前去MainVC的代码:

[self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];

这就是发生的事情:

页面没有展开。我遇到这种情况的原因是什么?

【问题讨论】:

【参考方案1】:

在我的实验中,您似乎无法在部分卷曲后进行标准演示(垂直封面),并同时关闭它们,除非您在动画设置为 NO 的情况下进行关闭。

解决此问题的一种方法是在没有动画的情况下关闭 secondVC(此代码在 secondVC 中):

-(IBAction)dismissSelf:(id)sender 
    [self dismissViewControllerAnimated:NO completion:nil];

然后在第一个VC中再次在viewDidAppear中用动画关闭,在测试控制器没有被呈现之后:

-(void)viewDidAppear:(BOOL)animated 
    if (![self isBeingPresented]) 
        [self dismissViewControllerAnimated:YES completion:nil];
    

虽然上面的代码可以返回到初始控制器的视图,但您会看到 firstVC 的视图出现在 curl 展开之前。如果您不想看到它,那么我能找到解决该问题的唯一方法是创建 secondVC 的图像,在解除 secondVC 之前将其作为(在图像视图中)子视图添加到 firstVC。因此,要做到这一点,secondVC 中的代码应该是这样的(请注意,您必须链接到 QuartzCore 并将其导入 secondVC 才能工作):

-(void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    UIImage *img = [self imageWithView:self.view];
    FirstViewController *first = (FirstViewController *)self.presentingViewController;
    UIImageView *iv = [[UIImageView alloc] initWithFrame:first.view.bounds];
    iv.image = img;
    [first.view addSubview:iv];



-(IBAction)dismissSelf:(id)sender 
    [self dismissViewControllerAnimated:NO completion:nil];



- (UIImage *)imageWithView:(UIView *)view 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;

【讨论】:

我已经通过使用 [self.presentingViewControllerdismissViewControllerAnimated:NO completion:^[[NSNotificationCenter defaultCenter] postNotificationName:@"BACKTOMAIN" object:nil];] 成功解决了这个问题;然后在接收控制器中,我添加了 [self dismissModalViewControllerAnimated:YES];也谢谢你的回答:)【参考方案2】:

你应该通过这个调用一个接一个地展示你的两个视图:

[self presentViewController:firstViewController animated:YES completion:^(
    [self presentViewController:secondViewController animated:YES completion:^(

    ];
];

这应该表现得更好。另外,请注意,之后您将不得不关闭这两个 viewController。

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:^
    [self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:^

    ];
];

【讨论】:

感谢您的回答。但是只有在单击第一个控制器视图内的按钮后才会调用第二个视图控制器。 啊,那么请确保在结束后将它们都拉下来。 您好 HalR,您的回答帮助了我。我所做的是在完成块内发布通知。 code[self.presentingViewControllerdismissViewControllerAnimated:NO 完成:^[[NSNotificationCenter defaultCenter] postNotificationName:@"BACKTOMAIN" object:nil];];【参考方案3】:

看起来您正在解雇“第一”而不是“第二”。

Apple 推荐的执行此操作的方法是委托。

尝试让 mainVC 成为 'first' 的委托,以便 first 可以调用 mainVC 的方法来解除自身。通过声明 'first' 的 'delegate' 属性并在实例化 'first' 时将其设置为 mainVC 来做到这一点。然后在 first.h 中定义一个 'firstDelegate' 协议,其中包括一些像'dismissFirst' 这样的函数,然后在 mainVC 中导入 first.h。现在在 mainVC 中实现dismissFirst 以实际关闭“first”并在第一个显示完成后做任何你想做的事情。

喘气...现在以同样的方式让 'first' 成为 'second' 的代表,只需让 'dismissSecond' 函数调用 mainVC 的 'dismissFirst' 函数,一切都会正常。

我知道这有点复杂,但委托是 ios 的核心概念,这是使用它的典型示例。

这里很好地解释了它是如何工作的。 http://chrisrisner.com/31-Days-of-iOS--Day-6%E2%80%93The-Delegate-Pattern

祝您在永无止境的探索中好运,以了解 Apple 工程师(也称为 Obj-C)的内在阴谋。

【讨论】:

解散多个在链中相互呈现的控制器很好。如果您解雇链中的第一个,则所有其他人都将被解雇。在这种特定情况下,问题是由于演示风格搞砸了。 我已经通过使用HalR给出的代码和一些修改解决了这个问题。我添加了一个通知以关闭另一个控制器。【参考方案4】:

我也有同样的疑问。我用其他方式解决了 -

第 1 步:在全局类(单例)中,您可以定义变量标志。

@property (nonatomic) int flag;

第 2 步:假设您需要关闭 second view controllerfirst view controller 并返回到 Main view controller ,同时关闭第二个视图控制器,您可以将此值设置为 假设 1

[[Global sharedObject] setFlag:1];
[self.navigationController popViewControllerAnimated:YES];

第3步:在first view controller- (void)viewWillAppear:(BOOL)animated方法中你可以设置这个方法——

if([[Global sharedObject] flag] == 1)

    [[Global sharedObject] setFlag:0];
    [self performSelector:@selector(back) withObject:nil afterDelay:0.5];


- (void) back

[self.navigationController popViewControllerAnimated:YES];

我希望你的答案可以使用这个来解决。如果你还有疑问,你可以问。干杯:)

【讨论】:

【参考方案5】:

您需要使用unwind segue。在您想要连接到的视图控制器中创建一个“空”IBAction。

@IBAction func unwindToController(segue: UIStoryboardSegue) 


然后转到您的故事板并选择您想要来自的控制器。在所选控制器顶部的图标中,最左边应该是一个黄色圆圈,中间有一个白色小方块,也就是文件所有者。按住 Ctrl 并拖动到要展开的视图控制器的“退出”标签。出口可以在控制器树的底部附近找到,或者在情节提要上作为最右边的红色正方形图像,其中带有带有右箭头的白色正方形。这将弹出一个对话框,选择您创建的unwindToController 操作。

一个新的“Unwind segue to Exit”将出现在您的 FROM 控制器中。双击它并给它一个标识符,例如unwindIdentifier

现在,当您想要展开两个控制器时,在您的 FROM 控制器中,使用:

self.performSegueWithIdentifier("unwindIdentifier", sender:nil)

这将跳过中间控制器并展开到第二个控制器,仅在动画中显示 TO 控制器。

【讨论】:

【参考方案6】:
- (UIViewController*)topViewController

    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (topController.presentedViewController) 
        topController = topController.presentedViewController;
    
    return topController;



- (void)dismissAllModalController

    __block UIViewController *topController = [self topViewController];

    while (topController.presentingViewController) 
        [topController dismissViewControllerAnimated:NO completion:^

        ];
        topController = [self topViewController];
    

【讨论】:

以上是关于关闭两个模态视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何连续关闭两个模态视图控制器*动画*?

在 Swift 中显示和关闭模态视图控制器

关闭当前的模态视图控制器,然后呈现新的模态视图控制器

如何关闭模态视图控制器,然后立即让呈现视图控制器呈现不同的模态视图控制器?

在后台关闭模态视图控制器

关闭模态视图控制器后呈现不同的视图控制器