dismissViewControllerAnimated:completion:未执行

7
当我调用dismissViewControllerAnimated:completion:来解散一个UIViewController时,当相应的视图正在使用presentViewController:animated:completion:进行屏幕动画时,完成块永远不会执行。 UIViewController甚至没有消失。就像dismissViewControllerAnimated:completion:被忽略了一样。
以下代码是一个简化的代码示例,因为原始代码要复杂得多。我提供的代码模拟了一个使用情况,在这种情况下,网络通信错误可能触发一个视图弹出,而同时也可能弹出另一个视图。
代码示例:
NSLog(@"Presenting view");

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

NSLog(@"Dismissing view");

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

日志输出如下:

2013年08月28日16:14:12.162 [1708:c07] 展示视图
2013年08月28日16:14:12.178 [1708:c07] 解除视图
2013年08月28日16:14:12.583 [1708:c07] 视图展示完成


有谁知道如何在这种情况下解除UIViewController?

先谢谢了。


这是什么类型的 UIViewController?你自己继承了它还是使用了第三方库? - Peter Warbo
它是一个子类化的UIViewController。但并没有什么特别的。它只是展示一些文本和一个按钮。 - MhaW
我已经添加了代码到原始帖子中以进行说明。@CaptJak 我设置了断点,它像正常一样步进。 - MhaW
3
我的猜测是,在可以关闭视图控制器之前,您需要等待视图控制器被呈现。 - Scott Berrevoets
实际上这只是一个简化的代码示例,因为原始代码要复杂得多。我提供的代码模拟了一种使用情况,即在同时弹出另一个视图的情况下,网络通信错误可能会触发一个视图弹出。 - MhaW
显示剩余7条评论
3个回答

5
这段代码片段不起作用的原因是这些方法中的完成块在动画完成后的稍后时间执行。您可以从日志中看到:"关闭视图"发生在"视图完成呈现"之前。请改用以下代码:
NSLog(@"Presenting view");

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

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

编辑:

如果您需要确保视图在网络错误发生时被关闭,请尝试设置一个名为networkErrorFound的布尔实例变量。

当您完成网络连接时,如果出现错误,请将其设置为YES。然后使用以下代码:

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

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

那样做,它会等到展示完成后再关闭。你还需要处理错误发生在动画完成后的情况(例如,一个最终失败的缓慢连接),但这超出了本问题的范围。

1
+1。但他为什么要一个接一个地展示和解雇呢?他是想用他的VC来吸引人们的注意吗?我可以想象一场诉讼正在途中,声称他的应用程序会导致癫痫发作 :) - CaptJak
但是,当我在两个调用之间加入睡眠(从而阻止UIThread)时,presentViewControllerAnimated:completion:的完成块也不会被调用。所以我认为完成实际上是在UIThread上运行的..? - MhaW
非常抱歉因为我的代码示例造成了困惑。我已经编辑了帖子,指出它实际上是一个简化的代码示例,因为原始代码要复杂得多。我提供的代码模拟了一个使用情况,其中网络通信错误可能会触发一个视图弹出,同时另一个视图也正在弹出 - 我试图保持简单,但似乎失败了..:( - MhaW
@MhaW 好的,我编辑了答案,也许这会对你有所帮助...不过我仍然不太确定你想要什么。 - aopsfan
我想我会这样做。感谢大家的帮助! - MhaW

1
为什么在加载完成后不将其关闭?
[self presentViewController:changeLocationViewController animated:YES completion:^{
    NSLog(@"View done presenting");

    NSLog(@"Dismissing view");

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

1
哇哈哈,我比你快了7秒钟 :-) - aopsfan

0

好的。看起来你想展示一个VC,但如果没有找到网络,就关闭VC。我能想到唯一需要这样做的原因是,如果网络只在你要展示的新VC中进行检查(并且希望在连接失败时关闭它)。

你可以通过实现@aopsfan给出的答案中所示的代码来实现这一点。

但是考虑一下UI流程。你告诉一个饥饿的人(用户)他可以吃一个三明治(他想看到的下一个VC)...但等等!(关闭想要的VC)不,你不能吃三明治(没有网络)!愚弄了你!

保持UI流畅而不令人恼火的方法是,在展示VC之前检查网络连接。可能在用于展示新VC的IBAction(?)中检查网络。这样,你可以在展示之前检查。而不是展示-取消

甚至可以显示一个HUD“正在进行”视图,让用户知道发生了什么!


应用程序中的网络连接是全局的。如果网络连接丢失,无论用户在应用程序中的哪个位置,应用程序都会关闭用户正在进行的任何操作,并显示“网络连接丢失”视图。 - MhaW
@MhaW,这没有任何区别。你仍然应该在呈现下一个视图控制器之前检查它。 - CaptJak
嗯,我不同意。我有一个处理网络相关事务的类,带有看门狗等功能,特别是为了避免在各处检查网络连接.. 但这是另一个话题,哈哈!:) 但还是谢谢你的想法和时间!:) - MhaW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接