Carl Sjogreen Carl Sjogreen - 1 year ago 87
Objective-C Question

How do I update the StatusBar Style as part of a custom transition

I'm using the iOS 7

protocol to present a modal
with a custom animation. The animation works correctly, however, I want the newly presented
to have a different status bar style than the presenting VC.

What I'm seeing is that
gets called on the PRESENTING
(several times in fact) and never on the newly presented
. If I remove the custom animation everything with the status bar works as I'd expect.

Is there something special I need to do in my animateTransition function to update the root view controller or something? I've tried manually setting the statusBar with
[UIApplication sharedApplication] setStatusBarStyle
but it doesn't work (I think because I'm using the ios 7 view controller based status bar styling).

This is my code for animateTransition:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
UICollectionViewCell *activeCell;
if ([self.collectionView.visibleCells containsObject:self.cellForActiveIdeaVC]) {
activeCell = self.cellForActiveIdeaVC;

UIView *container = transitionContext.containerView;
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *fromView = fromVC.view;
UIView *toView = toVC.view;

CGRect beginFrame;
if (activeCell) {
beginFrame = [container convertRect:activeCell.bounds fromView:activeCell];
} else {
beginFrame = CGRectMake(container.width / 2, container.height / 2, 0, 0);

CGRect endFrame = [transitionContext initialFrameForViewController:fromVC];

UIView *move = nil;
if (toVC.isBeingPresented) {
toView.frame = endFrame;
move = [toView snapshotViewAfterScreenUpdates:YES];
move.frame = beginFrame;
} else {
if (activeCell) {
move = [activeCell snapshotViewAfterScreenUpdates:YES];
} else {
move = [fromView snapshotViewAfterScreenUpdates:YES];
move.frame = fromView.frame;
[fromView removeFromSuperview];
[container addSubview:move];

[UIView animateWithDuration:.5
move.frame = toVC.isBeingPresented ? endFrame : beginFrame;
completion:^(BOOL finished) {
[move removeFromSuperview];

if (toVC.isBeingPresented) {
toView.frame = endFrame;
[container addSubview:toView];
} else {
if (self.cellForActiveIdeaVC) {
self.cellForActiveIdeaVC = nil;

[transitionContext completeTransition:YES];

Any pointers much appreciated!

Answer Source

With iOS 7 custom transitions, it's possible to present a view controller that isn't fullscreen and therefore wouldn't affect the statusbar appearance. You have to explicitly tell iOS that your custom presented view controller will, in fact, control the status bar's appearance.

UIViewController *controllerToPresent = [...]
controllerToPresent.modalPresentationStyle = UIModalPresentationStyleCustom;
controllerToPresent.modalPresentationCapturesStatusBarAppearance = YES;

[self presentViewController:controllerToPresent animated:YES completion:nil];

There's some more information here. Hope that helps!