iOS 9 custom transition - animationControllerForDi

2019-07-11 09:54发布

问题:

I am a newbee in iOS development and recently run into this problem with customized transition in iOS 9.

I have an object conforms to UIViewControllerTransitioningDelegate protocol and implements animationControllerForDismissedController, something like:

@implementation MyCustomizedTransitioningDelegate

#pragma mark - UIViewControllerTransitioningDelegate

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    MyCustomizedTransitionAnimator *animator = [[MyCustomizedTransitionAnimator alloc] init];
    animator.presenting = NO;
    return animator;
}

@end

And the process that triggers the modal transition is something like:

@implementation MyViewController

#pragma mark - Initializers

+ (MyCustomizedTransitioningDelegate *)modalTransitioningDelegateSingletonInstance;
{
    static MyCustomizedTransitioningDelegate *delegateInst = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        delegateInst = [[MyCustomizedTransitioningDelegate alloc] init];
    });

    return delegateInst;
}

#pragma mark - UIViewController

- (void)dismissViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion;
{
    [self prepareForDismissViewControllerAnimated:animated completion:&completion];
    [super dismissViewControllerAnimated:animated completion:completion];
}

- (void)prepareForDismissViewControllerAnimated:(BOOL)animated completion:(dispatch_block_t *)completion;
{
    self.presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
    self.presentedViewController.transitioningDelegate = [[self class] modalTransitioningDelegateSingletonInstance];      
}

@end

Since animationControllerForDismissedController method is not called, the MyCustomizedTransitionAnimator is not created, which leads to its animateTransition not called either, which causes unexpected problem in my app. (Sorry for my poor English...)

I am also attaching the screenshot of stack trace for both iOS8 & iOS9. In iOS 8, animationControllerForDismissedController is called after the stack trace below.

But in iOS9, transitionDidFinish is called somehow in advance, which I guess probably prevent animationControllerForDismissedController being called?

I was wondering if this is an iOS 9 bug or not. Any explanation or work around solution will be greatly appreciated!

回答1:

I faced the same issue.

I hope this will help someone.

What fixed it for me is to make the object which applies UIViewControllerTransitioningDelegate protocol as variable instance to keep strong relationship with it.

I think because it gets dismissed after the view is presented first time.



回答2:

I had the same issue.

Turned out I needed to set the delegate on the navigationController of the UIViewController that contains the trigger button.

Having this old code that didn't work:

UIViewController *dvc = [self sourceViewController];
TransitionDelegate *transitionDelegate = [TransitionDelegate new];

dvc.modalPresentationStyle = UIModalPresentationCustom;
dvc.transitioningDelegate = transitionDelegate;

[dvc dismissViewControllerAnimated:YES completion:nil];

I changed the first line to:

UIViewController *dvc = [self sourceViewController].navigationController;

and it worked.

Hope this helps.



回答3:

You need to say something like:

MyDestinationViewController *viewController = [[MyDestinationViewController alloc] init];
MyCustomizedTransitioningDelegate *transitioningDelegate = [[MyCustomizedTransitioningDelegate alloc]init];
viewController.transitioningDelegate = transitioningDelegate;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController: viewController animated:YES completion:nil];

Or if you're using segues, in prepareForSegue say something like:

MyDestinationViewController *toVC = segue.destinationViewController;
MyCustomizedTransitioningDelegate *transitioningDelegate = [[MyCustomizedTransitioningDelegate alloc]init];
toVC.transitioningDelegate = transitioningDelegate;