7

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

在呈现的视图控制器中,我有一个连接到按钮的 unwind segue。segue 开火就好了;呈现视图控制器中的IBAction方法被调用,呈现视图控制器中的方法也是如此prepareForSegue。但是,呈现的视图控制器不会被关闭,并且适当的转换委托方法 ( animationControllerForDismissedController:) 不会被调用。

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

我完全不知道在这里做什么。我查看了 Apple 的文档,并没有注意到任何说在处理自定义转换时必须对展开 segues 做一些特殊的事情。

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

任何帮助将非常感激,

提前致谢

4

2 回答 2

1

似乎如果您使用UIModalPresentationCustom自定义过渡管理器向控制器呈现,您还需要使用自定义过渡管理器来关闭它(我想这是有道理的,因为您可以在 animator 对象和 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")
    }
}
于 2015-07-21T14:47:42.773 回答
0

当我需要从模态呈现的视图传回数据时,我也遇到了这个问题。我在谷歌和这里徘徊了几个小时,但我找不到对我来说容易理解的答案。但我确实得到了一些提示,这是一个解决方法。似乎是因为它必须将数据传回,并且自动 Unwind 的解除过程先于数据传递,这阻止了 ViewController 被解除。所以我认为我必须再次手动关闭它。

我在这里得到了一些运气。我没有注意到它是一个子视图控制器。我只是从情节提要中配置它。

然后在 Unwind 函数中,我添加了行以删除子视图控制器和子视图。我在 sourceViewController 中没有代码。

斯威夫特 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()


    }
于 2018-08-26T17:04:14.810 回答