iOS-UIViewController的preferredsStatusBarHidden无法正常工作

我试图隐藏我的一个视图控制器的状态栏(以模态显示时)。 当我呈现视图控制器时,状态栏将被隐藏,然后在关闭时返回。

我已将以下代码添加到呈现的视图控制器中

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

我还将Info.plist文件中的密钥设置为以下内容:

<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

据我了解,这应该是完成这项工作所需要的。

我还使用自定义动画控制器来进行符合setNeedsStatusBarAppearanceUpdate协议的演示。 在animateTransition:的实现中,我尝试手动调用prefersStatusBarHidden,然后依次调用setNeedsStatusBarAppearanceUpdate以确保进行了调用,但状态栏仍然保留。

任何想法为什么会发生这种情况将不胜感激。 我已经搜索了StackOverflow,但似乎没有人遇到过这个问题,所有接受的答案都涉及到致电setNeedsStatusBarAppearanceUpdate,我已经在这样做了。

编辑-现在下面的代码似乎可以按需工作

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    if (self.isPresenting) {
        UIView *containerView = [transitionContext containerView];

        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        toViewController.view.frame = containerView.frame;

        [containerView addSubview:toViewController.view];

        // Ask the presented controller whether to display the status bar
        [toViewController setNeedsStatusBarAppearanceUpdate];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        // do the reverse
        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
            // Once dismissed - ask the presenting controller if the status bar should be presented
            [toViewController setNeedsStatusBarAppearanceUpdate];
        }];
    }
}

....

// PresentingController.m
- (BOOL)prefersStatusBarHidden
{
    if (self.presentedViewController) {
        return YES;
    }
    return NO;
}

// PresentedController.m
- (BOOL)prefersStatusBarHidden
{
    return YES;
}
4个解决方案
114 votes

在iOS7中,UIViewController实际上有一个名为YES的新属性。AppleiOS参考。

默认值为“否”。

当您通过调用presentViewController:animated:completion:方法来呈现视图控制器时,只有当所呈现的控制器的modalPresentationStyle值为UIModalPresentationFullScreen时,状态栏外观控件才会从呈现状态转移到呈现的视图控制器。 通过将此属性设置为YES,即使显示为非全屏显示,也可以指定显示的视图控制器控件状态栏的外观。

对于全屏显示的视图控制器,系统将忽略此属性的值。

因此,对于除普通全屏之外的任何PresentationStyle(例如:UIModalPresentationCustom),如果要捕获状态栏,则必须设置此样式。 要使用它,您所要做的就是在显示的视图控制器上将其设置为YES

toVC.modalPresentationCapturesStatusBarAppearance = YES;
David Liu answered 2020-07-30T15:27:55Z
17 votes

我要猜测(受过教育,但仍然是猜测),这是因为当您使用自定义过渡来执行呈现的视图控制器时,在iOS 7中,旧的视图控制器仍然存在。 因此,它可能仍然有发言权。

您甚至可以在其prefersStatusBarHidden中设置一个断点以查看; 如果未实施,则必须实施。 默认值为“否”,因此,如果进行协商,则可以解释您的结果。

如果我是对的,则需要实现旧的视图控制器的prefersStatusBarHidden,以给出两个不同的答案,具体取决于它是否具有presentedViewController

编辑我现在已经确认了这一点。 比我想象的还要糟糕。 在我的测试中,根本没有调用第二个视图控制器的prefersStatusBarHidden。 整个事情在第一个视图控制器的手中。 这是有道理的,因为正如我所说,第一个视图控制器永远不会消失; 使用自定义的演示动画,第二个视图控制器从属于第一个视图,因为第二个视图可以部分地悬停在第一个视图上。

因此,您将不得不完全从第一个视图控制器驱动状态栏。 您可以通过调用[self setNeedsStatusBarAppearanceUpdate]来调用其prefersStatusBarHidden。根据情况,您需要给出其他答案。 这可能有点棘手。 这是一个简单的实现,但可能无法涵盖所有情况:

// ViewController1:

-(void)setHide:(NSNumber*)yn {
    self->hide = [yn boolValue]; // a BOOL ivar
    [self setNeedsStatusBarAppearanceUpdate];
}
-(BOOL)prefersStatusBarHidden {
    return self->hide;
}
- (IBAction)doButton:(id)sender {
    self->hide = YES;
    [self setNeedsStatusBarAppearanceUpdate];
    [self presentViewController:[ViewController2 new] animated:YES completion:nil];
}

// ==========

// ViewController2:

- (IBAction)doButton:(id)sender {
    [self.presentingViewController setValue:NO forKey:@"hide"];
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
matt answered 2020-07-30T15:28:34Z
1 votes

如果它不起作用,并且您的UIViewController是UINavigationController中的子级,则此代码可能是您的解决方案。

open override var prefersStatusBarHidden: Bool {
    return topViewController?.prefersStatusBarHidden ?? super.prefersStatusBarHidden
}

基本上,UINavigationController使用它自己的preferredsStatusBarHidden值,但是在我的情况下,我想通过其顶部视图控制器的层次结构属性来覆盖它。

Konrad Siemczyk answered 2020-07-30T15:28:58Z
0 votes

您可以将其添加到info.plist

“查看基于控制器的状态栏外观”并将值设置为“否”

zuyao88 answered 2020-07-30T15:29:22Z
translate from https://stackoverflow.com:/questions/23615647/uiviewcontrollers-prefersstatusbarhidden-not-working