UIViewControllerTransitionCoordinator cannot coordinate view controller presentation animations along-side UIPropertyAnimator based animators

We use a UIPresentationController to coordinate animations for a presented view controller's veil (Apple called this "Chrome" in the WWDC 2014 session 228 - A Look Inside Presentation Controllers). The code below has been working on iOS 10 and now appears to be broken on iOS 11 as the UIView.alpha changes within the coordinator's animationAlongTransition block do not animate anymore, nor do they reverse if the transition is cancelled (didn't complete). From what I can tell, this breakage only occurs when using UIPropertyAnimator() since our other UIView.animate() based animators work just fine.


Expected Results:

The veil (chrome) in the sample code has a background color of UIColor(red: 1, green: 0, blue: 0, alpha: 0.4) for easy detection. The expectation is that as the view controller is presented, the veil animates from alpha 0 to alpha 1 behind the view controller inside of the transition container. Logically, as the view controller is dismissed, the veil animates from alpha 1 to alpha 0. The veil animation should also animate appropriately when the transition is interactive based on the transition context's percent complete.



Observed Results:

The observed results is that on iOS 10, everything works perfectly. On any version of the iOS 11 beta, the veil does not animate and instantly has it's alpha set. If a dismiss does not complete, the veil also does not revert back to it's original alpha.


Apple support, for full code sample with animators please see attachement in bug report with ID: 34136178.



@interface ModalPresentationController: UIPresentationController
@end
@implementation ModalPresentationController {
    UIView *veil;
}
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController {
    if (self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController]) {
        veil = [[UIView alloc] init];
        veil.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4f];
    }
    return self;
}
- (void)presentationTransitionWillBegin {
    veil.frame = self.containerView.bounds;
    veil.alpha = 0.0f;
    [self.containerView insertSubview:veil atIndex:0];

    [self.presentedViewController.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        veil.alpha = 1.0f;
    } completion:nil];
}
- (void)dismissalTransitionWillBegin {
    [self.presentedViewController.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        veil.alpha = 0.f;
    } completion:nil];
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    veil.size = size;
}
@end

Replies

I know this doesn't help, but I figured it should be documented.


I am also experiencing "instant" animations with a custom UIPresentationController. Almost identical code, but in Swift.


iOS 10 works fine with either Xcode 8 or 9. iOS 11 does not work. the


presentedViewController.transitionCoordinator?.transitionDuration


is always 0 which would imply no animations.


Please advise.



UPDATE:


I found that if I use a UIViewPropertyAnimator within an older UIView.animate block things kinda work again..

@master-nevimaster-nevi


Did you find help?

I'm experiencing this same issue. Would be great to have an Apple employee acknowledge this issue and give me some hope that it will be fixed.

Still running into this today. It looks like this is fixed as of iOS 11.3, so to support older versions, I have this method in my UIPresentationController subclass:

Code Block swift
internal func animateDimmingViewDisappearing() {
    guard let dimmingView = dimmingView,
        let transitionCoordinator = presentedViewController
            .transitionCoordinator
        else { return }
    // Despite this API being available earlier, iOS 11.3 is the first OS
    // that doesn’t just animate this instantly.
    if #available(iOS 11.3, *) {
        transitionCoordinator.animateAlongsideTransition(
            in: dimmingView.superview,
            animation: { _ in dimmingView.alpha = 0 },
            completion: { _ in dimmingView.removeFromSuperview() }
        )
    } else {
        UIView.beginAnimations("animateDimmingViewDisappearing",
                               context: nil)
        if transitionCoordinator.transitionDuration > 0 {
            UIView.setAnimationDuration(
                transitionCoordinator.transitionDuration
            )
        }
        else {
            UIView.setAnimationDuration(1.0 / 3.0)
        }
        UIView.setAnimationCurve(transitionCoordinator.completionCurve)
        dimmingView.alpha = 0
        UIView.commitAnimations()
    }
}