自定义故事板Segue在模拟器中工作,但不在设备上

时间:2014-10-08 09:54:34

标签: ios iphone swift segue uistoryboardsegue

我一直收到错误:

*** 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.'

尝试切换到新的视图控制器时。以下是segue切换视图控制器:

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 个答案:

答案 0 :(得分:2)

通常该错误表示您正在尝试执行推送segue,并且呈现视图控制器不受UINavigationController管理。简单的解决方案通常是将显示(即从)视图控制器嵌入导航控制器中,如NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController中所述。

但是既然你已经推出了自己的UIStoryboardSegue课程,我怀疑你并不想简单地使用默认的push segue动画。在不知道如何管理transitioningDelegate的情况下,我猜您需要实际覆盖perform()来呈现视图控制器而不是推送它:

override func perform() {
    let fromVC  = sourceViewController as UIViewController
    let toVC    = destinationViewController as UIViewController

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