I've been working to implement a custom modal transition that uses a UIPresentationController
subclass to create and manipulate an additional view during the presentation and dismissal. Apple helpfully provides an example of how to do this in the documentation, but I've hit a snag.
When presenting the modal, my custom view animations work perfectly, but when I dismiss the modal, the animations applied to the custom views in dismissalTransitionWillBegin
play out of sync with the animations specified by the transition animator object I'm returning from animationControllerForDismissedController:
. Specifically, the custom view's animations are ignoring the duration of the transition animation and are always playing very quickly (the duration appears to be around 0.2 seconds).
What could cause animateAlongsideTransition:completion:
to ignore the duration of the base animation?
The source of the trouble appears to be a bug in iOS.
No matter how I refactored or simplified my animation code, I always ended up with the same result, so I started to wonder if there might be something in the way my project was set up that was causing the problem. I dropped my custom modal transition code into a clean project and, lo and behold, it worked perfectly on the first try.
Bit by bit I customized my test app to more closely match my real app and I was eventually able to get the problem to reappear. Through trial and error I found the combination of factors that was triggering the problem:
UINavigationController
UIBarButtonItem
When those three conditions are met, the animation block of the animateAlongsideTransition:
call in dismissalTransitionWillBegin
will be performed before the animation block of the animateWithDuration:
call in animateTransition
. This seems to prevent the custom view's animations from getting the transition animation's duration. In my testing, the animateAlongsideTransition:
animations ran with a duration of 0.215 seconds, which I believe is the default duration.
I have been unable to find any way prevent the issue from occurring other than removing one of the three factors triggering it. The workaround I ultimately settled on was removing the window's tint color and instead setting a global tint color using UIView
's appearance proxy. There are some side-effects--like UIAlertView
s' buttons getting tinted--, but for my purposes this was an acceptable trade-off.