I'm implementing a custom interactive collection view layout transition, and would like to configure it so that on calling finishInteractiveTransition
with a transition layout transitionProgress
of 1.0, the completion block of startInteractiveTransitionToCollectionViewLayout:completion:
is fired immediately.
I require this behaviour as I would like to be able to immediately start another transition after this one has finished. With this completion block not firing immediately, I end up with nested push animation can result in corrupted navigation bar
in the log, since the transition context hasn't had its completeTransition:
method called yet.
As it is, even when there is no animation required, there is a small delay of about 0.05s. Is it possible to force UICollectionView
to not animate this completion?
Some code...
I have a transition controller that handles both animated & interactive transitions for a navigation transition. The relevant parts of that controller are as follows:
- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
self.context = transitionContext;
UIView *inView = [self.context containerView];
UICollectionViewController *fromCVC = (UICollectionViewController *)[self.context viewControllerForKey:UITransitionContextFromViewControllerKey];
UICollectionViewController *toCVC = (UICollectionViewController *)[self.context viewControllerForKey:UITransitionContextToViewControllerKey];
self.transitionLayout = (MyTransitionLayout *)[fromCVC.collectionView startInteractiveTransitionToCollectionViewLayout:toCVC.collectionViewLayout completion:^(BOOL completed, BOOL finish) {
[self.context completeTransition:completed];
[inView addSubview:toCVC.view];
}];
}
- (void)updateInteractiveTransition:(CGFloat)progress
{
if (!self.context) return;
self.percentComplete = progress;
if (self.percentComplete != self.transitionLayout.transitionProgress) {
self.transitionLayout.transitionProgress = self.percentComplete;
[self.transitionLayout invalidateLayout];
[self.context updateInteractiveTransition:self.percentComplete];
}
}
- (void)finishInteractiveTransition
{
if (!self.context) return;
UICollectionViewController *fromCVC = (UICollectionViewController *)[self.context viewControllerForKey:UITransitionContextFromViewControllerKey];
[fromCVC.collectionView finishInteractiveTransition];
[self.context finishInteractiveTransition];
}
- (void)cancelInteractiveTransition
{
if (!self.context) return;
UICollectionViewController *fromCVC = (UICollectionViewController *)[self.context viewControllerForKey:UITransitionContextFromViewControllerKey];
[fromCVC.collectionView cancelInteractiveTransition];
[self.context cancelInteractiveTransition];
}
I've verified that on calling finishInteractiveTransition
the transition layout's transitionProgress
is exactly 1.0. According to the UIViewControllerTransitioning.h
header file, the completionSpeed
defaults to 1.0, resulting in a completion duration of (1 - percentComplete)*duration
, so the duration should be 0, but it's not... it's taking at least a couple of run loops before the completion block is called.
Is it possible to do what I want, or will I have to implement my own version of startInteractiveTransitionToCollectionViewLayout:completion:
? (not the end of the world, but I'd rather stick to the standard APIs where possible...)