Unwind Segue不会使用UIModalPresentationCustom解除View Controller

bax*_*rma 7 uiviewcontroller ios uimodalpresentationstyle unwind-segue

我(通过其设置呈现使用自定义过渡模态的视图控制器modelPresentationStyleUIModalPresentationCustom,提供了一个过渡代表,和UIViewControllerAnimatedTransitioning对象).

在提供的视图控制器中,我有一个unwind segue连接到一个按钮.塞古火灾很好; IBAction调用呈现视图控制器中的方法,并且在呈现的视图控制器中也是如此prepareForSegue.但是,呈现的视图控制器不会被解除,并且animationControllerForDismissedController:不会调用适当的转换委托方法().

但是,如果我将呈现的视图控制器设置modalPresentationStyleUIModalPresentationFullScreen(默认值),则视图控制器将被正确解除(但这会破坏我的自定义转换).

我完全不知道该做什么.我查看了Apple的文档,并没有注意到任何说在处理自定义转换时必须使用unwind segue做特殊事情的事情.

我知道我可以使用呈现视图控制器dismissViewControllerAnimated:completion:IBAction方法调用,但我宁愿使用它作为最后的手段,让它按照它应该的方式工作(或者至少知道它为什么不起作用:) ).

任何帮助将非常感激,

提前致谢

Kub*_*der 1

看来,如果您使用UIModalPresentationCustom自定义转换管理器来呈现控制器,则还需要使用自定义转换管理器来关闭它(我猜这是有道理的,因为您可以在动画器对象和 UIKit 中执行各种奇怪的操作不能确定像往常一样关闭屏幕就会完全恢复原始状态 - 我只是希望它明确地告诉你......)。

以下是我在应用程序中修复此问题所做的操作:

  • segueForUnwindingToViewController在父视图控制器(您在关闭动画后移动到的视图控制器)中覆盖并返回您的实例,UIStoryboardSegue可以是您用于原始转换的实例,也可以是一个新的单独类
  • 如果 unwind segue 的目标视图控制器位于导航层次结构中,那么您需要在导航控制器中重写该方法
  • perform方法调用中dismissViewControllerAnimated
  • 所呈现的视图控制器仍然需要保留对转换委托的有效引用,否则您将获得 EXC_BAD_ACCESS (请参阅DismissViewControllerAnimated EXC_Bad_ACCESS on true) - 因此要么使其保持委托作为该线程中描述的强引用,要么分配在调用之前换一个新的dismissViewControllerAnimated(也可能modelPresentationStyle在关闭之前更改为全屏也可以,但我还没有尝试过)
  • 如果解除动画需要执行任何非标准操作(幸运的是我没有),请animationControllerForDismissedController在过渡管理器对象中覆盖并返回正确的动画器
  • 如果目标视图控制器位于导航层次结构中,那么您还需要在关闭显示的屏幕之前手动将导航堆栈弹出到目标控制器(即target.navigationController!.popToViewController(target, animated: false)

完整代码示例:

// custom navigation controller 

override func segueForUnwindingToViewController(toViewController: UIViewController,
fromViewController: UIViewController,
identifier: String?) -> UIStoryboardSegue {
    return CustomSegue(
        identifier: identifier,
        source: fromViewController,
        destination: toViewController
    )
}


// presented VC

var customTransitionManager: UIViewControllerTransitioningDelegate?


// custom segue

override func perform() {
    let source = sourceViewController as! UIViewController

    if let target = destinationViewController as? PresentedViewController {
        let transitionManager = TransitionManager()
        target.modalPresentationStyle = .Custom
        target.customTransitionManager = transitionManager
        target.transitioningDelegate = transitionManager

        source.presentViewController(target, animated: true, completion: nil)
    } else if let target = destinationViewController as? WelcomeViewController {
        target.navigationController!.popToViewController(target, animated: false)
        target.dismissViewControllerAnimated(true, completion: nil)
    } else {
        NSLog("Error: segue executed with unexpected view controllers")
    }
}
Run Code Online (Sandbox Code Playgroud)