使用自定义转换时视图控制器是不是会被完全删除?

Posted

技术标签:

【中文标题】使用自定义转换时视图控制器是不是会被完全删除?【英文标题】:Does a view controller get removed entirely when using a custom transition?使用自定义转换时视图控制器是否会被完全删除? 【发布时间】:2018-02-03 17:53:49 【问题描述】:

我有两个视图控制器。在第一个上,我有一个按钮,它以模态方式显示第二个。然后,我通过点击它上的一个按钮来关闭第二个(它会关闭)。为了解除过渡,我创建了一个符合 UIViewControllerAnimatedTransitioning 的自定义类,因此我为视图控制器使用自定义过渡动画(我需要在解除过渡期间自定义行为)。

我的问题如下:由于我使用了自定义转换,我的视图控制器在转换完成后是否仍会被删除,还是仍然存在但不在屏幕上?如果是的话,会不会影响记忆,有多严重?

【问题讨论】:

【参考方案1】:

你说:

我的视图控制器在转换完成后是否仍会被删除,还是仍然存在但不在屏幕上?

这里有两个完全不同的问题。

首先,有一个视图控制器层次结构的问题。当你呈现一个新的视图控制器时,旧的视图控制器总是保留在视图控制器层次结构中,这样当你解散它时,它仍然会在那里。但是,当您关闭时,被关闭的视图控制器将从视图控制器层次结构中删除,并且(除非您做一些不寻常的事情,例如在某处保留您自己对它的强引用)它将被释放。

其次,视图层次结构有一个单独的问题。呈现时,UIPresentationController 指示呈现视图控制器的视图是否保留在视图层次结构中。默认情况下,它将它保留在视图层次结构中,但通常如果执行模态全屏“呈现”,您将指定一个UIPresentationController 子类,告诉它在转换完成时删除呈现视图控制器的视图。


例如,在执行自定义模态“呈现”转换时,呈现的视图控制器的视图是不透明的并覆盖整个屏幕,那么您的UIViewControllerTransitioningDelegate 不仅会提供动画控制器,还会指定呈现控制器:

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? 
    return YourAnimationController(...)


func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? 
    return YourAnimationController(...)


func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? 
    return PresentationController(presentedViewController: presented, presenting: presenting)

并且该演示控制器可能相当小,只告诉它删除演示者的视图:

class PresentationController: UIPresentationController 
    override var shouldRemovePresentersView: Bool  return true 

【讨论】:

感谢您的详尽回答。提供新的view controller 时会调用方法presentationController(forPresented:presenting:source),对吗?那么,如果我仍然使用默认的模态 segue 动画来呈现新的 view controller 而我使用自定义的动画来关闭它呢? 我猜它会被删除(因为默认的模态演示总是从视图层次结构中删除演示者的视图),但它可能会检查你的演示控制器做了什么。我建议您只使用 Xcode 视图调试器并确认。就个人而言,如果我自己制作解散动画,我总是会实现自己的演示动画。您不希望看到未来的某些 ios 版本以某种方式更改演示动画,从而破坏您的应用程序。 好的,谢谢您的建议。我还将创建一个自定义演示动画。关于演示者的视图:如果模态 segue 的 presentationStyle 设置为 overCurrentContext(或 overFullScreen),视图仍然存在,对吗?我记得,我遇到过这种行为(演示者的视图在 Xcode 视图调试器中仍然可见)。对于那种presentationStyle,这是正常的行为吗? The documentation says 表示,“当您想使用自定义模式呈现类型呈现视图控制器时,请将其 modalPresentationStyle 属性设置为 custom 并将符合此协议的对象分配给其transitioningDelegate 财产。”正如文档所说使用custom,我没有尝试过其他modalPresentationStyle 设置(我不确定我是否建议这样做)。 好的,罗伯。感谢您的帮助。【参考方案2】:

ViewController 保留在层次结构中。

您可以通过验证模态视图控制器中self.parentViewController 属性的值来确认这一点。

编辑:

那个视图控制器会影响内存吗?

是的,它将继续在 parentViewController 中执行所有操作或活动(例如:流式音频、播放动画、运行计时器等)。

如果是这样,如何处理这种情况?

UIViewController 类中有一些方法可以检测 ViewController 何时会出现/消失。 更具体地说,您可以使用以下方法:

    viewWillAppear(通知视图控制器其视图即将添加到视图层次结构中) viewDidAppear(通知视图控制器其视图已添加到视图层次结构中) viewWillDisappear(通知视图控制器其视图即将从视图层次结构中删除) viewDidDisappear(通知视图控制器其视图已从视图层次结构中删除)

您可以在parentViewController 中使用viewWillAppearviewDidAppear 来启动或恢复此类活动/操作。 和viewWillDisappearviewDidDisappear 暂停或停止此类活动/操作。

希望这会有所帮助。

【讨论】:

我刚刚在我的项目中测试了它,在我的情况下,它甚至在调用completeTransition(使用present(vc, animated: true, completion: nil) 呈现)之前为零..知道怎么回事吗? 感谢您的回答。那么,view controller 会影响内存吗(我认为会)?如果是这样,这种情况如何处理? 好的。谢谢你的回答【参考方案3】:

我将假设您正在谈论您的模态 viewControllerview 留在窗口层次结构中 - 因为您询问它是否仍然存在但不在屏幕上,我相信您在谈论视图和控制器,因为控制器从不在屏幕上。

如果您询问view(我假设您是这样),在transitionContext 上调用completeTransition 会将其从窗口层次结构中删除(因此无需调用fromVC.view.removeFromSuperview()) -根据合同,您需要在 UIViewControllerAnimatedTransitioning 实现中的转换完成时调用 completeTransition

您可以通过在调用transitionContext.completeTransition 前后检查fromVC.view.superview 的值来确认此行为:

UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: 
    fromVC.view.frame = endFrame
)  (_) in
    print(">>> \(fromVC.view.superview)")
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    print(">>> \(fromVC.view.superview)")

【讨论】:

【参考方案4】:

是的,之前的 UIViewController 仍然存在。 如Apple docs 中所述

viewControllerToPresent 显示在视图上的视图控制器 当前视图控制器的内容。

【讨论】:

那么,当我使用自定义转换时会发生这种行为,还是使用模态转场时总是会发生这种情况? ViewController - 保留在层次结构中。视图 - 正如 Rob 所提到的,它提供了从层次结构中删除演示者视图的选项。

以上是关于使用自定义转换时视图控制器是不是会被完全删除?的主要内容,如果未能解决你的问题,请参考以下文章

UIViewController 自定义转换和状态恢复

视图是黑色的,当返回到导航控制器堆栈视图时,在实现自定义转换后

自定义容器和自定义转换

导航时如何在 SwiftUI 中使用自定义视图转换?

ES自定义分词器

Xib 自定义 UIView 的实例化