Pangu
Pangu

Reputation: 3819

Having trouble with UIView slide animation from left to right?

I'm trying to animate 2 UIViews, UIView1 is present, and upon a button tap, UIView2 slides from right to left and occupies the screen, moving UIView1 out of the way.

That part I am able to achieve successfully with slideLeftTransitionFromView. However, upon a button tap again to slide UIView1 from left to right with slideRightTransitionFromView, UIView1 somehow disappears during the animation. UIView2 does slide successfully out of the way from left to right, but I cannot see UIView1.

I'm sure slideRightTransitionFromView follows similar logic as slideLeftTransitionFromView, but I'm having trouble getting it working.

Here's the 2 functions:

func slideLeftTransitionFromView(view: UIView, toView: UIView, duration: NSTimeInterval, completion: ((Bool) -> Void)?)
{
    if let container = view.superview
    {
        // Final position of outgoing view
        let outgoingViewEndX = view.frame.origin.x - view.frame.size.width

        // Final position of incoming view (existing frame)
        let incomingViewEndX = view.frame.origin.x

        // Start point of incoming view -- at the right edge of the outgoing view
        let incomingViewStartX = view.frame.origin.x + view.frame.size.width

        // Distance traveled by outgoing view
        let outgoingDisplacement = view.frame.origin.x - outgoingViewEndX

        toView.frame.origin = CGPointMake(incomingViewStartX, toView.frame.origin.y)
        container.addSubview(toView)

        dispatch_async(dispatch_get_main_queue(), { ()
            UIView.animateWithDuration(duration, delay: 0, options: .CurveLinear, animations: {

                view.frame.origin.x = outgoingViewEndX
                toView.frame.origin.x = incomingViewEndX

                }, completion: {(complete: Bool) in

                    // If the outgoing view is still in onscreen, keep sliding until it's offscreen
                    if outgoingViewEndX + view.frame.size.width > 0 {

                        // Adjust the duration for the final animation based on the distance it has to travel in order to keep the same velocity.
                        let finalDuration = duration * Double((outgoingViewEndX + view.frame.size.width)/outgoingDisplacement)

                        UIView.animateWithDuration(finalDuration, delay: 0, options: .CurveLinear, animations: {

                            view.frame.origin.x = -view.frame.size.width
                            }, completion: { (complete: Bool) in
                                completion?(complete)
                                view.removeFromSuperview()
                        })
                    }
                    else
                    {
                        completion?(complete)
                        view.removeFromSuperview()
                    }
            })
        })
    }
}

func slideRightTransitionFromView(view: UIView, toView: UIView, duration: NSTimeInterval, completion: ((Bool) -> Void)?)
{
    if let container = view.superview
    {
        // Final position of outgoing view
        let outgoingViewEndX = view.frame.origin.x + view.frame.size.width

        // Final position of incoming view (existing frame)
        let incomingViewEndX = view.frame.origin.x

        // Start point of incoming view -- at the left edge of the outgoing view
        let incomingViewStartX = view.frame.origin.x - view.frame.size.width

        // Distance traveled by outgoing view
        let outgoingDisplacement = view.frame.origin.x + outgoingViewEndX

        toView.frame.origin = CGPointMake(incomingViewStartX, toView.frame.origin.y)
        container.addSubview(toView)

        dispatch_async(dispatch_get_main_queue(), { ()
            UIView.animateWithDuration(duration, delay: 0, options: .CurveLinear, animations: {

                view.frame.origin.x = outgoingViewEndX
                toView.frame.origin.x = incomingViewEndX

                }, completion: {(complete: Bool) in

                    // If the outgoing view is still in onscreen, keep sliding until it's offscreen
                    if outgoingViewEndX + view.frame.size.width < 0 {

                        // Adjust the duration for the final animation based on the distance it has to travel in order to keep the same velocity.
                        let finalDuration = duration * Double((outgoingViewEndX + view.frame.size.width)/outgoingDisplacement)

                        UIView.animateWithDuration(finalDuration, delay: 0, options: .CurveLinear, animations: {

                            view.frame.origin.x = view.frame.size.width
                            }, completion: { (complete: Bool) in
                                completion?(complete)
                                view.removeFromSuperview()
                        })
                    }
                    else
                    {
                        completion?(complete)
                        view.removeFromSuperview()
                    }
            })
        })
    }
}

It's likely something simple, but I can't see it. What seems to be the problem?

Thanks

Upvotes: 0

Views: 2009

Answers (1)

Shubhank
Shubhank

Reputation: 21805

You have probably declared the UIView IBOutlet as weak var

in slideLeftTransitionFromView calling view.removeFromSuperview() removes the view from view heirarchy and am pretty sure your view gets deallocated since it is a weak var and not part of the layout anymore.

Therefore you dont see it when you try to add it again as subview later on. Try making the var strong reference.

Upvotes: 1

Related Questions