【问题标题】:Can you detect when a UIViewController has been dismissed or popped?你能检测到 UIViewController 何时被解除或弹出吗?
【发布时间】:2014-10-27 18:38:42
【问题描述】:

每当我的视图控制器之一被解除/弹出/卸载时,我需要在共享资源中执行一些清理工作?这可能是当用户点击单个屏幕上的后退按钮时,也可能是调用了 popToRootViewController(在这种情况下,我最好能够清除每个弹出的控制器。)

显而易见的选择是在 viewDidUnload 中执行此操作,但当然,卸载不是这样工作的。有没有办法捕捉到 ViewController 从堆栈中移除的所有情况?

编辑:忘记提及我正在使用 Xamarin 执行此操作,因此可能会或可能不会影响答案。

【问题讨论】:

  • 此共享资源在何处/何时创建?需要进行什么样的清理工作?是否需要在应用程序中的任何视图控制器被解除或仅在特定视图控制器类的实例被解除时才执行此操作?
  • @rmaddy:资源在加载时添加到 viewController。清理是资源内部方法的一部分,该方法执行多项我不清楚的事情,但应该调用它。需要调用它来解除每个单独的控制器。如果我回击一个屏幕,该屏幕将需要在其对资源的引用上调用该方法。如果我有 4 个屏幕深并调用 popToRootViewController,则弹出的 3 个屏幕将每个都需要调用该方法。
  • 那么dealloc,正如@SteveMadsen 所说,可能是最好的地方。
  • 是的,看起来 dealloc 是 Objective-C 的正确答案。遗憾的是,我认为它不适用于 Xamarin,因此我仍在寻找解决方案。

标签: ios xamarin.ios xamarin


【解决方案1】:
override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    if (isBeingDismissed() || isMovingFromParentViewController()) {
        // clean up code here
    }
}

为 swift 4/5 编辑

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    if (isBeingDismissed || isMovingFromParent) {
        // clean up code here
    }
}

【讨论】:

  • 虽然这是推荐的方法(Apple),但在我的代码中,当dismissViewController 调用时它不起作用。也许那是因为我使用了自定义的关闭过渡。
  • 首先你必须在覆盖viewDidDisappear(_:)时调用super,否则可能会导致你的神奇错误。根据我的实验,虽然此解决方案在大多数情况下都有效,但当您在呈现的 vc 等上呈现 vc 时,除了导航堆栈中的最后一个视图控制器和嵌套(模态)呈现之外,它无法检测到 UINavigationController.popToRootViewController(animated:)。所以,如我认为这是相当不可靠的 + 小心/自律,凌乱dealloc,或所有自定义容器 vcs 和模态转换。
  • @MANIAK_dobrii 如果我检测到的 vc 是 tabbar->nav controller->vc1->vc2,你将如何处理这种情况(在调用 popToRootViewController 时在此处检测)->modal
  • @Cyber​​Mew 我会尽量避免“以通用方式”这样做。我不会尝试通过 UIKit 钩子检测 UIViewController 何时消失,而是将其全部翻转并明确此转换。这样我就不会在 vc2 中有代码检测解雇/弹出/任何内容,而是添加了一些可以解雇的内容(调用 popToRootViewController )并明确通知 vc2。或者,甚至将所有必需的东西移到 vc 之外,并以不需要任何类似簿记的方式设计 vc。具体解决方案视情况而定,只是你不必在vc中检测。
  • 实际上这行得通。 @Harris 可能您在错误的视图控制器上检查它。如果你将它嵌入到 NavigationController 中,它将仅在导航控制器上使用 isBeingDismissed=true 调用。
【解决方案2】:

-dealloc 可能是您最好的选择。视图控制器从堆栈中弹出时将被释放,除非您将其保留在其他地方。

viewWillDisappear:viewDidDisappear: 不是很好的选择,因为它们在视图控制器不再显示的任何时候都会被调用,包括当它将其他东西压入堆栈时(因此它变成了倒数第二个) .

viewDidUnload 不再使用。自 iOS 6 起,系统框架停止调用此方法。

【讨论】:

    【解决方案3】:

    根据@Enricoza 的评论,如果您确实将 UIViewController 嵌入到 UINavigationController 中,请尝试以下操作:

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        if ((navigationController?.isBeingDismissed) != nil) {
            // Add clean up code here
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多