如何检测 UINavigationController 动画何时完成?

Posted

技术标签:

【中文标题】如何检测 UINavigationController 动画何时完成?【英文标题】:How to detect when UINavigationController animation has finished? 【发布时间】:2012-04-14 01:24:50 【问题描述】:

我希望这是一个简单的问题。如果我有一个 UINavigationController 并且我将一个新的视图控制器推送到带有动画转换的堆栈上,我如何检测动画何时完成并且新的视图控制器在屏幕上?

我有一些场景需要推送一个新的控制器,然后必须执行长时间运行的操作。我想先推送新视图,以便在我开始长时间阻塞主线程之前屏幕上有一些东西。如果我在我的长时间运行的任务之后立即执行推送,则视图不会显示,直到两者都完成并且主线程能够再次处理事件之后。

所以,一旦动画完成并且视图出现在屏幕上,我想做的就是能够在新控制器中检测到,然后启动任务。

【问题讨论】:

【参考方案1】:

+1 对@DHamrick 的建议,即根本不阻塞主线程。

回答原问题,可以在两个地方检测viewController的变化:

    你刚刚推送的viewController会收到viewWillAppear:和viewDidAppear:消息。如果您想知道特定 viewController 何时出现,请实现这些方法。

    @Mike Z 提到的navigationController:didShowViewController:animated: 方法被发送到navigationController 的delegate。您需要指定一个对象作为该委托方才能接收此消息。然后,您将知道每次 viewController 出现。

【讨论】:

视图控制器上的 viewDidAppear 似乎是我想要的。我不能在单独的线程上完成这项工作,因为正在执行的代码不是线程安全的。感谢所有的建议。 谢谢你的回答对我有帮助【参考方案2】:

您应该考虑在另一个线程内执行长时间运行的操作,甚至更好,使用 GCD 队列,而不是阻塞主线程。

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, NULL);
dispatch_async(backgroundQueue, ^
    // Do your long running code
    dispatch_async(dispatch_get_main_queue(), ^
        //Update your UI
    );
);

您可以将此代码放在您的viewDidLoad: 中,以便您知道您的 UI 已经加载。这也意味着您不必依赖动画的时间安排。

【讨论】:

顺便说一句,为什么dispatch_get_global_queue() 而不是dispatch_queue_create()?我一直使用后者,但回想起来,只有少数情况我需要严格的串行队列,但我想我可以转移到并发队列。没有明显的(例如,在需要时使用串行),有没有关于串行队列与并发队列的想法? 当我想保证对给定资源的单一访问时,我通常会创建一个队列。例如,如果我有一个我想保证不会同时访问的数据库连接。 是的,我使用队列是出于完全相同的原因,并且我会以这种方式保留队列(这是我对“我需要严格串行队列的地方”的引用)。但是我想我刚刚养成了总是创建自己的队列的习惯,但是您让我意识到这不是必需的(并且可能不是很好地利用系统资源)。我将开始更多地使用dispatch_get_global_queue()。感谢您的洞察力。 (顺便说一句,这就是我喜欢 SO 的原因。) 我试图编辑帖子,但我的编辑太短了。请注意,这应该是 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);,在这里传递 NULL 会导致警告。【参考方案3】:

我自己没有测试或实现过这个,但文档听起来像:

navigationController:didShowViewController:animated:

描述为:在导航控制器显示视图控制器的视图和导航项属性之后发送给接收者。

否则,

setAnimationDidStopSelector: 可能适合您。

描述为:设置动画停止时发送给动画代理的消息。

【讨论】:

以上是关于如何检测 UINavigationController 动画何时完成?的主要内容,如果未能解决你的问题,请参考以下文章

UINavigationController

UINavigationController 风格

全屏显示 ViewController

多控制器

UINavigationControllerDelegate 不起作用

viewController 出现时出现黑色