I am presenting my custom UIViewController
(called "temp") with a custom animation. The UIVC gets called with:
[temp setModalPresentationStyle:UIModalPresentationCustom];
temp.transitioningDelegate = self;
[temp.view setHidden:YES];
[self presentViewController:temp animated:YES completion:nil];
My custom animation is presenting a view modally from right to top-left position of the screen. It is being presented hidden so the user doesn't see the animation. After it reaches the SCREEN_HEIGHT (768) position it is being set to visible and animated (moved) from top to bottom being presented in the middle. The goal was to present a view from top to bottom and dismiss it from top to bottom (like a movie scene). This code is the NOT working one:
- (void)animateTransition:(id)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
NSLog(@" fromViewController %@ ",fromViewController);
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
NSLog(@" toViewController %@ ",toViewController);
UIView *containerView = [transitionContext containerView];
if (self.presenting)
{
// set starting rect for animation toViewController.view.frame = [self rectForDismissedState:transitionContext];
[containerView addSubview:toViewController.view];
[UIView animateWithDuration:0.5
animations:^{
toViewController.view.frame = CGRectMake(-self.customSize.width, self.yValue, self.customSize.width, self.customSize.height);
}
completion:^(BOOL finished)
{
//HERE IS THE PROBLEM!!!
[toViewController.view setHidden:NO];
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
CGRect variable = [self rectForPresentedState:transitionContext];
CGRect fitToCurrentScreenResolution = CGRectMake(0, 0, variable.size.width, variable.size.height);
toViewController.view.frame = fitToCurrentScreenResolution;
}
completion:^(BOOL finished)
{
[transitionContext completeTransition:YES];
}];
}];
}
else
{
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
fromViewController.view.frame = [self rectForDismissedState:transitionContext];
}
completion:^(BOOL finished)
{
[transitionContext completeTransition:YES];
[fromViewController.view removeFromSuperview];
}
];
}
}
And here is the solution:
- (void)animateTransition:(id)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
NSLog(@" fromViewController %@ ",fromViewController);
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
NSLog(@" toViewController %@ ",toViewController);
UIView *containerView = [transitionContext containerView];
if (self.presenting)
{
// set starting rect for animation toViewController.view.frame = [self rectForDismissedState:transitionContext];
[containerView addSubview:toViewController.view];
[UIView animateWithDuration:0.5
animations:^{
toViewController.view.frame = CGRectMake(-self.customSize.width, self.yValue, self.customSize.width, self.customSize.height);
}
];
[toViewController.view setHidden:NO];
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
CGRect variable = [self rectForPresentedState:transitionContext];
CGRect fitToCurrentScreenResolution = CGRectMake(0, 0, variable.size.width, variable.size.height);
toViewController.view.frame = fitToCurrentScreenResolution;
}
completion:^(BOOL finished)
{
[transitionContext completeTransition:YES];
}];
}
else
{
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
fromViewController.view.frame = [self rectForDismissedState:transitionContext];
}
completion:^(BOOL finished)
{
[transitionContext completeTransition:YES];
[fromViewController.view removeFromSuperview];
}
];
}
}
My question is simple. Why is my UIVC being presented twice?
I have tried making my custom UIVC a property which is lazy loaded but my app crashes saying that a UIVC = nil can not be presented modally.
I have tried this solution, but it didn't apply to my problem :viewWillAppear being called twice in iOS5
I also did this with no help: Calling presentModalViewController twice?
I could have used a hack but I wouldn't find out why it is happening. So far it seems that when the animation enters the completion BLOCK it calls the view again.
The apple docs say:
A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL.
Is the view being drawn again since the next run loop cycle is being started? NOTE: Even thought the view is being presented twice, the viewDidLoad method is being called only once.
I would like to know why this is happening. There are some stackoverflow questions with the same code but with different usage scenarios having the same problem without a working solution or explanation.
Thank you for any advice/comment.