سؤال

I'm presenting a modal UINavigationController with an interactive dismiss transition. The parent view controller has a dark status bar and the modal view controller a light status bar. I'm using the iOS 7 view controller-based status bar appearance configuration.

All works fine as long as I present and dismiss the view controller non-interactively. However, when I start an interactive dismiss transition and cancel it, the status bar color remains dark.

I created a sample project. Tap the "Menu" button, then start the interactive transition by panning from the right screen edge.

Things I've tried:

  • calling -setNeedsStatusBarAppearanceUpdate on any of the navigation and view controllers involved after the transition has been canceled
  • Changing the navigationBar.barStyle to UIBarStyleDefault and back to UIBarStyleBlack

I also verified that the statusBarStyle of my modal navigation controller is set correctly:

(lldb) p (UIStatusBarStyle) [[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentedViewController] preferredStatusBarStyle]
(UIStatusBarStyle) $8 = UIStatusBarStyleLightContent

Still, the status bar is black.

Any further idea what I could try?

هل كانت مفيدة؟

المحلول

To me this looks like a bug (rdar://15902745) in UINavigationController. After a canceled dismissal UINavigationController doesn't query again its presentedViewController for the preferredStatusBarStyle but uses the preferredStatusBarStyle from itself. I worked around this by overwriting -childViewControllerForStatusBarStyle:

- (UIViewController*)childViewControllerForStatusBarStyle {
    if (self.presentedViewController) {
        return self.presentedViewController.childViewControllerForStatusBarStyle;
    }

    return [super childViewControllerForStatusBarStyle];
}

Then, to animate the change during (and not after) the dismissal, I also overwrote -preferredStatusBarStyle.

I pushed the workaround to the sample project.

نصائح أخرى

Do not forget to call

[self.transitionContext cancelInteractiveTransition];

within your's UIPercentDrivenInteractiveTransition subclasses - (void)cancelInteractiveTransition implementation. For inspiration, this is mine implementation

- (void)cancelInteractiveTransition {

id<UIViewControllerContextTransitioning> transitionContext = self.transitionContext;
[transitionContext cancelInteractiveTransition];

UIView *fromView = [UIViewController fromViewForTransitioningContext:transitionContext];
UIView *toView = [UIViewController toViewForTransitioningContext:transitionContext];

if (self.presenting)
{
    CGRect endFrame = CGRectOffset([[transitionContext containerView] bounds], 0, CGRectGetHeight([[transitionContext containerView] bounds]));

    [UIView animateWithDuration:ANIMATION_DURATION_PAN animations:^{

        toView.frame = endFrame;

    } completion:^(BOOL finished) {

        [transitionContext completeTransition:NO];
    }];
}
else {

    CGRect endFrame = [[transitionContext containerView] bounds];

    [UIView animateWithDuration:ANIMATION_DURATION_PAN animations:^{
        fromView.frame = endFrame;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:NO];
    }];
}

}

edit: this seems to help on iOS 8.4. Tested on 7.1 but no way. Maybe Apple fixed it lately.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top