Search code examples
iosswiftsegueuistoryboardsegueunwind-segue

segueForUnwindingToViewController causing "Warning: Attempt to present <...> on <...> which is already presenting <...>"


I am building an app and recently discovered a huge memory leak caused by traditional segues. Therefore I learned about unwind segue. Everything works just fine if I simply use:

    @IBAction func prepareForUnwindToMainFromFriends(segue: UIStoryboardSegue) {
    }

Memory leak is solved and 'everything is awesome'. But this solution looks ugly on a UI point of view. So I implemented this function from this website. And changed it a little.

override func segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue {
    return UIStoryboardSegue(identifier: identifier, source: fromViewController, destination: toViewController) {
        let fromView = fromViewController.view
        let toView = toViewController.view
        if let containerView = fromView.superview {
            let initialFrame = fromView.frame
            var offscreenRect = initialFrame
            var offscreenRectFinal = initialFrame
            offscreenRect.origin.x += CGRectGetWidth(initialFrame)
            offscreenRectFinal.origin.x -= CGRectGetWidth(initialFrame)
            toView.frame = offscreenRect
            containerView.addSubview(toView)
            let duration: NSTimeInterval = 1.0
            let delay: NSTimeInterval = 0.0
            let options = UIViewAnimationOptions.CurveEaseInOut
            let damping: CGFloat = 0.9
            let velocity: CGFloat = 4.0
            UIView.animateWithDuration(duration, delay: delay, usingSpringWithDamping: damping,
                initialSpringVelocity: velocity, options: options, animations: {
                    toView.frame = initialFrame
                    fromView.frame = offscreenRectFinal
                    
                }, completion: { finished in
                    fromView.removeFromSuperview()
                    if let navController = toViewController.navigationController {
                        navController.popToViewController(toViewController, animated: false)
                    }
            })
        }
    }
}

But now I get an error message:

2015-05-12 08:47:31.841 PING0.4[4343:1308313] Warning: Attempt to present <NotificationViewController: 0x177030b0>  on <PING0_4.ViewController: 0x16271000> which is already presenting <NotificationViewController: 0x1a488170>

And I am blocked in my app. I can go from VC1 to VC2, then back to VC2 but then I cannot get back to VC1 again. It looks like I can only use this segue once.

Any one has any idea of what is going on?


Solution

  • Created Sample code for unwind segue with above transition animation code. Checkout SampleUnwind project that will help you to understand unwind segue(and how simple it is).

    In project there is one navigation controller and inside it there are three view controller (Home->First->second).

    In Home controller following unwind action is created, which will be called when 'Home' button of second controller is tapped(simple unwind stuff).

    @IBAction func unwindToHomeViewController(segue:UIStoryboardSegue) {
    }
    

    I have created TempNavigationController subclassing UINavigationController and set that TempNavigationController to navigation controller in storyboard. Above method you given is pesent inside it as this will be container of fromViewController as per following referance.

    Reference: Apple documentation about Transitioning Between Two Child View Controllers.

    You can compare this with your project and maybe you can find any duplicate(or multiple/wrong) segue in your project.