如何防止源视图控制器在推送后消失?
How do I keep the source view controller from disappearing after a push segue?
首先,这是我的观点 controller/segue 设置:
最右边的三个视图控制器的背景视图是 UIVisualEffectViews,源视图控制器应该通过它们可见。它们被添加到各种 viewDidLoad()
中,如下所示:
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = self.view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.tableView.backgroundView = blurEffectView
现在,通过设置视图控制器可以看到主视图控制器("Garbage Day" 那个),但是只要最右边的两个 VC 之一出现,设置 VC 就会消失完全在屏幕上。这是一个屏幕录像:
Screen recording of the source view controller dis- and reappearing
(请忽略小故障,我用来上传这个的应用程序显然损坏了视频)
从技术上讲,我明白了,Show segue 没有 "Over Current Context" 东西,因此,我不应该期望来源 VC 不会消失,但必须有办法使这项工作无需自定义 segues。
我建议您在视图控制器之间创建自定义转换。
我刚刚编写并测试了这个 class:
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning
{
var pushing = true
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let duration = transitionDuration(using: transitionContext)
let toVc = transitionContext.viewController(forKey: .to)!
let toView = transitionContext.view(forKey: .to)!
let fromView = transitionContext.view(forKey: .from)!
let container = transitionContext.containerView
if pushing {
container.addSubview(fromView)
container.addSubview(toView)
}
var finalFrame = transitionContext.finalFrame(for: toVc)
if pushing {
finalFrame.origin.x = finalFrame.width
toView.frame = finalFrame
finalFrame.origin.x = 0
} else {
finalFrame.origin.x = finalFrame.width
}
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
if self.pushing {
toView.frame = finalFrame
} else {
fromView.frame = finalFrame
}
}) { (_) in
transitionContext.completeTransition(true)
if self.pushing {
container.insertSubview(fromView, belowSubview: toView)
} else {
fromView.removeFromSuperview()
}
}
}
}
在您的 UINavigationController
class 中执行以下操作:
class NavigationController: UINavigationController {
let animationController = AnimationController()
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
}
还有这个扩展:
extension NavigationController: UINavigationControllerDelegate
{
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.pushing = operation == .push
return animationController
}
}
但是,这会使您失去交互式关闭手势(从屏幕左侧滑动以关闭),因此您需要自己修复。
首先,这是我的观点 controller/segue 设置:
最右边的三个视图控制器的背景视图是 UIVisualEffectViews,源视图控制器应该通过它们可见。它们被添加到各种 viewDidLoad()
中,如下所示:
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = self.view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.tableView.backgroundView = blurEffectView
现在,通过设置视图控制器可以看到主视图控制器("Garbage Day" 那个),但是只要最右边的两个 VC 之一出现,设置 VC 就会消失完全在屏幕上。这是一个屏幕录像:
Screen recording of the source view controller dis- and reappearing
(请忽略小故障,我用来上传这个的应用程序显然损坏了视频)
从技术上讲,我明白了,Show segue 没有 "Over Current Context" 东西,因此,我不应该期望来源 VC 不会消失,但必须有办法使这项工作无需自定义 segues。
我建议您在视图控制器之间创建自定义转换。
我刚刚编写并测试了这个 class:
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning
{
var pushing = true
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let duration = transitionDuration(using: transitionContext)
let toVc = transitionContext.viewController(forKey: .to)!
let toView = transitionContext.view(forKey: .to)!
let fromView = transitionContext.view(forKey: .from)!
let container = transitionContext.containerView
if pushing {
container.addSubview(fromView)
container.addSubview(toView)
}
var finalFrame = transitionContext.finalFrame(for: toVc)
if pushing {
finalFrame.origin.x = finalFrame.width
toView.frame = finalFrame
finalFrame.origin.x = 0
} else {
finalFrame.origin.x = finalFrame.width
}
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
if self.pushing {
toView.frame = finalFrame
} else {
fromView.frame = finalFrame
}
}) { (_) in
transitionContext.completeTransition(true)
if self.pushing {
container.insertSubview(fromView, belowSubview: toView)
} else {
fromView.removeFromSuperview()
}
}
}
}
在您的 UINavigationController
class 中执行以下操作:
class NavigationController: UINavigationController {
let animationController = AnimationController()
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
}
还有这个扩展:
extension NavigationController: UINavigationControllerDelegate
{
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.pushing = operation == .push
return animationController
}
}
但是,这会使您失去交互式关闭手势(从屏幕左侧滑动以关闭),因此您需要自己修复。