ios UIViewController 的 prefersStatusBarHidden 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23615647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:07:23  来源:igfitidea点击:

UIViewController's prefersStatusBarHidden not working

iosobjective-cios7uiviewcontrollerios7-statusbar

提问by Taz

I am trying to make the status bar for one of my view controllers to be hidden (when displayed modally). When I'm presenting the view controller, the status bar is is to be hidden and then returned when dismissed.

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

I have added the following code to the presented view controller

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

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

I have also set the keys in the Info.plist file to the following:

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

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

From my understanding this should be all that is required to make this work.

根据我的理解,这应该是完成这项工作所需的全部内容。

I am also using a custom Animation Controller to do the presenting which conforms to the UIViewControllerAnimatedTransitioningprotocol. In the animateTransition:implementation I have tried to manually call prefersStatusBarHidden, followed by setNeedsStatusBarAppearanceUpdateto ensure the call is being made, but the status bar remains.

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

Any ideas why this is happening would be appreciated. I have searched StackOverflow, but it appears no one has had this issue, all accepted answers refer to calling setNeedsStatusBarAppearanceUpdate, which I am already doing.

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

EDIT- The code below now seems to WORKas desired

编辑-下面现在的代码似乎工作的期望

- (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;
}

回答by David Liu

In iOS7, there's actually a new property for UIViewController called modalPresentationCapturesStatusBarAppearance. Apple iOS reference.

在 iOS7 中,实际上 UIViewController 有一个名为 的新属性modalPresentationCapturesStatusBarAppearance苹果 iOS 参考。

Default value is NO.

When you present a view controller by calling the presentViewController:animated:completion: method, status bar appearance control is transferred from the presenting to the presented view controller only if the presented controller's modalPresentationStyle value is UIModalPresentationFullScreen. By setting this property to YES, you specify the presented view controller controls status bar appearance, even though presented non–fullscreen.

The system ignores this property's value for a view controller presented fullscreen.

默认值为否。

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

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

Therefore, for any presentationStyle other than the normal fullscreen (for example: UIModalPresentationCustom), this must be setif you want to capture the status bar. To use, all you have to do is set it to YESon the view controller that's being presented:

因此,对于普通全屏以外的任何presentationStyle(例如:UIModalPresentationCustom),如果要捕获状态栏,则必须设置此项。要使用,您所要做的就是将其设置YES在正在呈现的视图控制器上:

toVC.modalPresentationCapturesStatusBarAppearance = YES;

回答by matt

I'm going to guess (educated, but still a guess) that this is because when you do a presented view controller using a custom transition, in iOS 7, the old view controller is still there. Therefore it probably still gets a say.

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

You might even put a breakpoint in itsprefersStatusBarHiddento see; you'll have to implement it if it isn't implemented. The default is NO, so if it is consulted, that would explain your result.

您甚至可以在其中放置一个断点prefersStatusBarHidden来查看;如果它没有实施,你将不得不实施它。默认值为 NO,因此如果咨询它,将解释您的结果。

If I'm right, you would need to implement the oldview controller's prefersStatusBarHiddento give two different answers, depending on whether it has a presentedViewControlleror not.

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

EDITI've now confirmed this. It's even worse than I thought; in my testing, the second view controller's prefersStatusBarHiddenisn't being called at all. The whole thing is in the hands of the first view controller. This makes sense because, as I said, the first view controller never goes away; with a custom presentation animation, the second view controller is subordinate to the first one, because the second view can hover partially over the first view.

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

Thus you're going to have to drive the status bar entirely from the first view controller. You can cause its prefersStatusBarHiddento be called by calling [self setNeedsStatusBarAppearanceUpdate]. You'll need to give a different answer depending on the circumstances. This can be a bit tricky. Here's a simple implementation, but it may not cover all the cases:

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

// 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];
}

回答by Konrad Siemczyk

If it's not working and your UIViewController is a child in UINavigationController, then this code might be a solution for you.

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

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

Basically the UINavigationController uses it's own prefersStatusBarHiddenvalue, but in my case I wanted to overwrite that by its top view controller's property in hierarchy.

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

回答by zuyao88

You may add this to info.plist

您可以将此添加到 info.plist

"View controller-based status bar appearance" and set the value to "No"

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