3

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. iOS 8

But in iOS9, transitionDidFinish is called somehow in advance, which I guess probably prevent animationControllerForDismissedController being called? iOS 9: <code>transitionDidFinish</code> is called

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

yvetterowe
  • 1,239
  • 7
  • 20
  • 34
  • How are you kicking off the modal transition, perhaps you could post code regarding that. – beyowulf Dec 16 '15 at 02:41
  • @beyowulf Just edited it. Thanks! – yvetterowe Dec 16 '15 at 03:16
  • Is there a reason you're wanting to use a singleton? Placing + (MyCustomizedTransitioningDelegate *)modalTransitioningDelegateSingletonInstance; in the view controller is awkward and likely why your delegate is not getting called. – beyowulf Dec 16 '15 at 03:27
  • Why don't you try setting the transitioningDelegate before you present the view controller as apple's own sample code does. If you don't want to provide a custom animation for the presentation of the view controller, in - animationControllerForPresentedController:presentingController:sourceController: return nil or don't implement it at all. Thousands of app have custom transition, and they still seem to work on iOS 9. – beyowulf Dec 18 '15 at 02:13
  • have you found solution for this issue ? – Mejdi Lassidi Feb 07 '16 at 16:55

3 Answers3

10

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.

Mejdi Lassidi
  • 999
  • 10
  • 22
  • This solved the issue for me. Simply changing the scope of the variable from method to class solved the issue. – Mani Dec 09 '18 at 22:56
4

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.

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
boreas
  • 1,041
  • 1
  • 15
  • 30
  • Perfect ! Need to set the `transitionDelegate` to the navigation controller if the modal is wrapped in it. – GoodSp33d Jun 09 '16 at 09:14
0

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;
beyowulf
  • 15,101
  • 2
  • 34
  • 40