执行自定义segue时调用不平衡

时间:2014-08-15 16:58:55

标签: ios swift segue

我创建了一个自定义segue,它是一个垂直segue的反转版本,这是我的执行功能:

var sourceViewController = self.sourceViewController as UIViewController!
var destinationViewController = self.destinationViewController as UIViewController!

sourceViewController.view.addSubview(destinationViewController.view)
destinationViewController.view.frame = sourceViewController.view.frame
destinationViewController.view.transform = CGAffineTransformMakeTranslation(0, -sourceViewController.view.frame.size.height)
destinationViewController.view.alpha = 1.0

UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
    destinationViewController.view.transform = CGAffineTransformMakeTranslation(0, 0)
    }) { (finished: Bool) -> Void in
            destinationViewController.view.removeFromSuperview()
            sourceViewController.presentViewController(destinationViewController, animated: false, completion: nil)
    }

当我在我的应用程序中执行它时它可以工作,动画正是我想要的但是我在控制台中有这个警告:

Unbalanced calls to begin/end appearance transitions for <Custom_Segues.ViewController: 0x7a3f9950>.

我在Stack Overflow上阅读了很多有关此问题的帖子,但我没有找到与我的情况相关的帖子,有人知道这是什么问题吗?我在代码上尝试了很多东西,我知道问题出现在最后两行,但我不知道要改变什么。

EDIT /解答:

在阅读答案后,我找到了一个解决方案:更改视图,然后在新视图上应用旧VC并执行动画。代码是安全的,动画结束时没有旧VC的闪存。

var sourceViewController = self.sourceViewController as UIViewController!
var destinationViewController = self.destinationViewController as UIViewController!
var duplicatedSourceView: UIView = sourceViewController.view.snapshotViewAfterScreenUpdates(false) // Screenshot of the old view.

destinationViewController.view.addSubview(duplicatedSourceView) // We add a screenshot of the old view (Bottom) above the new one (Top), it looks like nothing changed.

sourceViewController.presentViewController(destinationViewController, animated: false, completion: {
    destinationViewController.view.addSubview(duplicatedSourceView) // We add the old view (Bottom) above the new one (Top), it looks like nothing changed.

    UIView.animateWithDuration(0.33, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
        duplicatedSourceView.transform = CGAffineTransformMakeTranslation(0, sourceViewController.view.frame.size.height) // We slide the old view at the bottom of the screen
            }) { (finished: Bool) -> Void in
            duplicatedSourceView.removeFromSuperview()
        }
    })
}

2 个答案:

答案 0 :(得分:1)

这看起来与runloop时序有关。

destinationViewController.view.removeFromSuperview()
sourceViewController.presentViewController(destinationViewController, animated: false, completion: nil)

这两行不应该在同一个runloop中执行。

destinationViewController.view.removeFromSuperview()

// Force presentViewController() into a different runloop.
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
    sourceViewController.presentViewController(destinationViewController, animated: false, completion: nil)
}

答案 1 :(得分:1)

我将此添加为评论,但我认为它足以做出第二个解决方案。在查看 How to custom Modal View Controller presenting animation?

之后

解决方案转换为swift:

var transition = CATransition()
transition.duration = 1
transition.type = kCATransitionFade
transition.subtype = kCATransitionFromBottom

sourceViewController.view.window?.layer.addAnimation(transition, forKey: kCATransition)
sourceViewController.presentViewController(destinationViewController, animated:false, completion:nil)

您可以根据自己的需要进行调整。