Unwind Segue不会使用UIModalPresentationCustom解除View Controller

时间:2015-02-25 12:27:40

标签: ios uiviewcontroller uimodalpresentationstyle unwind-segue

我正在使用自定义转换(通过将其modelPresentationStyle设置为UIModalPresentationCustom,提供转换委托和UIViewControllerAnimatedTransitioning对象)来呈现模态视图控制器。

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

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

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

我知道我可以在呈现视图控制器的dismissViewControllerAnimated:completion:方法中调用IBAction,但我宁愿将其作为最后的手段使用,并让unwindwind segue正常运行它应该(或者至少知道为什么它不起作用:))。

非常感谢任何帮助,

提前致谢

2 个答案:

答案 0 :(得分:1)

似乎如果你使用UIModalPresentationCustom向控制器提供自定义转换管理器,你还需要使用自定义转换管理器来解除它(这是有道理的,因为你可以做各种各样的动画师对象中的奇怪东西和UIKit不能确定像往常一样只是解除屏幕将完全恢复原始状态 - 我只是希望它明确地告诉你......)。

以下是我在我的应用中解决此问题的方法:

  • 覆盖父视图控制器中的segueForUnwindingToViewController(在关闭动画后您要移动的那个)并返回UIStoryboardSegue的实例,或者是您用于原始视频的实例过渡或新的单独的课程
  • 如果展开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")
    }
}

答案 1 :(得分:0)

当我需要从模态表示的视图传回数据时,我也遇到了这个问题。 我在Google和这里徘徊了几个小时,但找不到适合我的简单答案。但是我确实得到了一些提示,这里有一个解决方法。 似乎是因为它必须将数据传回,并且自动Unwind的关闭过程是在数据传递之前进行的,这阻止了ViewController的关闭。因此,我认为我必须再次手动将其关闭。

我在这里很幸运。我没有注意到这是一个子视图控制器。我只是从情节提要中对其进行了配置。

然后在“展开”功能中,我添加到行中以删除子视图控制器和子视图。我的sourceViewController中没有代码。

Swift 4.1

@IBAction func unwindToVC(sender :UIStoryboardSegue){

    if let source = sender.source as? CoreLocationVC{
        if source.pinnedCity != nil{
             clCity = source.pinnedCity
        }
        if source.pinnedCountry != nil {
            clCountry = source.pinnedCountry
        }
        if source.pinnedTimeZone != nil {
            clTimeZone = source.pinnedTimeZone
        }
        if source.pinnedLocation != nil {
            clLocation = source.pinnedLocation
        }
        // I added 2 lines here and it just worked
        source.view.removeFromSuperview()
        source.removeFromParentViewController()


    }