自定义Storyboard Segue在模拟器上可以运行但是在设备上不行

3

I keep getting the error:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController.'

在尝试切换到新的视图控制器时,以下是切换视图控制器的转场:

image

即使我尝试将我的转场类名称放入Segue类中,它仍然会在我的设备上出现错误,但在模拟器中完全正常。

转场类的代码:

class TransitionManager: UIStoryboardSegue, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate  {

private var presenting = true

// MARK: UIViewControllerAnimatedTransitioning protocol methods

// animate a change from one viewcontroller to another
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    // get reference to our fromView, toView and the container view that we should perform the transition in
    let container = transitionContext.containerView()
    let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
    let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!

    // set up from 2D transforms that we'll use in the animation
    let π : CGFloat = 3.14159265359

    let offScreenRight = CGAffineTransformMakeRotation(-π/2)
    let offScreenLeft = CGAffineTransformMakeRotation/2)

    // prepare the toView for the animation
    toView.transform = self.presenting ? offScreenRight : offScreenLeft

    // set the anchor point so that rotations happen from the top-left corner
    toView.layer.anchorPoint = CGPoint(x:0, y:0)
    fromView.layer.anchorPoint = CGPoint(x:0, y:0)

    // updating the anchor point also moves the position to we have to move the center position to the top-left to compensate
    toView.layer.position = CGPoint(x:0, y:0)
    fromView.layer.position = CGPoint(x:0, y:0)

    // add the both views to our view controller
    container.addSubview(toView)
    container.addSubview(fromView)

    // get the duration of the animation
    // DON'T just type '0.5s' -- the reason why won't make sense until the next post
    // but for now it's important to just follow this approach
    let duration = self.transitionDuration(transitionContext)

    // perform the animation!
    // for this example, just slid both fromView and toView to the left at the same time
    // meaning fromView is pushed off the screen and toView slides into view
    // we also use the block animation usingSpringWithDamping for a little bounce
    UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.8, options: nil, animations: {

        // slide fromView off either the left or right edge of the screen
        // depending if we're presenting or dismissing this view
        fromView.transform = self.presenting ? offScreenLeft : offScreenRight
        toView.transform = CGAffineTransformIdentity

        }, completion: { finished in

            // tell our transitionContext object that we've finished animating
            transitionContext.completeTransition(true)

    })

}

// return how many seconds the transiton animation will take
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
    return 0.75
}

// MARK: UIViewControllerTransitioningDelegate protocol methods

// return the animataor when presenting a viewcontroller
// remmeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {

    // these methods are the perfect place to set our `presenting` flag to either true or false - voila!
    self.presenting = true
    return self
}

// return the animator used when dismissing from a viewcontroller
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    self.presenting = false
    return self
}

override func perform() {
    //
}

}

我有什么遗漏吗?或者如何让这个工作起来?

1个回答

2
通常,这个错误表示您正在尝试执行 push segue,而 presenting view controller 没有由 UINavigationController 管理。简单的解决方案通常是将 presenting(即 from)view controller 嵌入导航控制器中,如 NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController 中所述。
但是,由于您自己编写了 UIStoryboardSegue 类,我怀疑您并不仅仅想使用默认的 push segue 动画。如果不知道您如何管理 transitioningDelegate,我猜测您需要实际上重写 perform() 方法来呈现您的 view controller,而不是将其推送。
override func perform() {
    let fromVC  = sourceViewController as UIViewController
    let toVC    = destinationViewController as UIViewController

    fromVC.presentViewController(toVC as UIViewController, animated: true, completion: nil)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接