Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom animation of segue is not played the first time tapping the button

I encountered an unusual behavior on which I am stuck a little, the problem is the following.

I'm using BWWalkthrough library in order to have a 4 slides as launch screen. So in my appdelegate i have the following code which initialize the viewcontrollers:

let storyboard = UIStoryboard(name: "SlidesFlow", bundle: nil)

let walkthrough = storyboard.instantiateViewController(withIdentifier: "SlidesView") as! BWWalkthroughViewController
let page_zero = storyboard.instantiateViewController(withIdentifier: "page_1")
let page_one = storyboard.instantiateViewController(withIdentifier: "page_2")
let page_two = storyboard.instantiateViewController(withIdentifier: "page_3")
let page_three = storyboard.instantiateViewController(withIdentifier: "page_4")

walkthrough.delegate = self
walkthrough.addViewController(page_zero)
walkthrough.addViewController(page_one)
walkthrough.addViewController(page_two)
walkthrough.addViewController(page_three)

Everything works as intended, so no problem here. On the viewController page_three i have a button which redirect me to an other view controller using a custom segue animation

class sentSegueFromRight: UIStoryboardSegue {

override func perform()
{
    let src = self.source as UIViewController
    let dst = self.destination as UIViewController

    src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
    dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)

    UIView.animate(withDuration: 0.25,
                               delay: 0.0,
                               options: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
        },
                               completion: { finished in
                                src.present(dst, animated: false, completion: nil)
        }
    )
}
}

Now the problem is, if i use the same code on a normal viewcontroller the button and the animation work without issues. The problem is when i use the segue defined above from the last slide of my BWWalkthrough. The first time i tapp the button the viewcontroller which should appear does appear but without the corresponding animation. After closing it and taping on the button again the animation is played but an error is returned:

Presenting view controllers on detached view controllers is discouraged

If i use the button with the standard animation ( without using my custom animation code ) i get no error and the default animation is played.

I can't seem to find a solution to this problem. Does anybody stumbled upon something like this?

like image 902
Netra Avatar asked Sep 30 '16 16:09

Netra


1 Answers

The problem here lies in the BWWalkthrough library which is using a scrollview to present all the views of the various ViewControllers that you add.

As such, you add the dst.view at the beginning of the scrollview (at offset screenwidth,0) which you then transform to offset (0,0).

All of this is offscreen as you are currently in the third screen of the walkthrough (at offset (screenwidth*3,0)). As such you don't get to see the animation and directly see the presented view controller when the segue ends.

To remedy this, add your dst.view in the segue to the superview of the scrollview. i.e. instead of src.view.superview?.insertSubview(dst.view, aboveSubview: src.view) write src.view.superview?.superview?.insertSubview(dst.view, aboveSubview: src.view) in the segue. (Assuming that you are using the segue only from the walkthrough)

If you intend to use the segue in other places too, then you can maybe add a type check in the segue to check if the superview of src.view is a scrollview, if yes, add dst.view to the superview of the scrollview.

like image 179
Amit Gupta Avatar answered Oct 31 '22 09:10

Amit Gupta