使用自定义转换时视图控制器是不是会被完全删除?
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
中使用viewWillAppear
和viewDidAppear
来启动或恢复此类活动/操作。
和viewWillDisappear
和viewDidDisappear
暂停或停止此类活动/操作。
希望这会有所帮助。
【讨论】:
我刚刚在我的项目中测试了它,在我的情况下,它甚至在调用completeTransition
(使用present(vc, animated: true, completion: nil)
呈现)之前为零..知道怎么回事吗?
感谢您的回答。那么,view controller
会影响内存吗(我认为会)?如果是这样,这种情况如何处理?
好的。谢谢你的回答【参考方案3】:
我将假设您正在谈论您的模态 viewController
的 view
留在窗口层次结构中 - 因为您询问它是否仍然存在但不在屏幕上,我相信您在谈论视图和控制器,因为控制器从不在屏幕上。
如果您询问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 所提到的,它提供了从层次结构中删除演示者视图的选项。以上是关于使用自定义转换时视图控制器是不是会被完全删除?的主要内容,如果未能解决你的问题,请参考以下文章