如何在子视图控制器中更改iOS状态栏颜色

如何在子视图控制器中更改iOS状态栏颜色,ios,objective-c,cocoa-touch,uiviewcontroller,uistatusbar,Ios,Objective C,Cocoa Touch,Uiviewcontroller,Uistatusbar,(iOS 7 Xcode 5.0.2) 我使用了以下方法,成功地将根视图控制器上的状态栏颜色更改为白色 [self setNeedsStatusBarAppearanceUpdate]; // Update status bar style -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; // Set status bar color to white } 现在,当导航

(iOS 7 Xcode 5.0.2)

我使用了以下方法,成功地将根视图控制器上的状态栏颜色更改为白色

[self setNeedsStatusBarAppearanceUpdate]; // Update status bar style

-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent; // Set status bar color to white
}
现在,当导航到子视图控制器时,我尝试将状态栏颜色更改为黑色,我不知道如何操作。(状态栏颜色仍然为白色)

我搜索并找到了这个方法:childViewControllerForStatusBarStyle 我读了苹果的文档,但仍然不知道如何/在哪里使用它,我不确定这是否是正确的方法


有人知道如何更改子视图控制器中的状态栏颜色吗?

默认情况下,
UINavigationController
不幸的是,它没有为状态栏样式提供合理的默认实现。通过实现此方法,您可以告诉navigationController将对
preferredStatusBarStyle
的所有调用推迟到其最顶层的childViewController

extension UINavigationController {
  override open var childViewControllerForStatusBarStyle: UIViewController? {
    return visibleViewController
  }
}
您可以将
UINavigationController
子类化并在其中实现该方法,也可以简单地添加一个类别:

@implementation UINavigationController (ChildStatusBarStyle)

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

@end
我刚刚发现: 当您将根视图控制器正确地嵌入到UINavigationController中时,您就不需要创建一个类别来扩展导航控制器的功能,也不需要为相同的目的对UINavigationController进行子类化

您只需将
preferredStatusBarStyle
放入每个视图控制器中,并记住调用
[self-setNeedsStatusBarAppearanceUpdate]以更新状态栏样式。虽然很简单

查看WWDC 2013的视频:


编辑:

我之所以让它工作,是因为我碰巧把UINavigationBar设为隐藏状态。在这种情况下,当根本不使用UINavigationController时,它的行为相同。
尝试更改UINavigationController堆栈中的UIViewController的StatusBarStyle时。这样做是行不通的。它仅适用于单个UIViewController。WWDC 2013视频示例未使用UINavigationController,因此该方法运行良好。

与James Frost所说的相反,在花费大量时间调试为什么我的浏览器活动的状态栏颜色错误(Swift)后:

也就是说:在某些情况下.topViewController是正确的,在其他情况下,如UIActivities,它是.visibleViewController。

答案是唯一对我有效的答案。非常感谢。这是该代码的Swift 4版本

extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
    return topViewController
}
}
extension UINavigationController {
  override open var childViewControllerForStatusBarStyle: UIViewController? {
    return visibleViewController
  }
}
注意:这有点笨拙,我建议添加一些代码,将其范围限制为单个viewController。大概是这样的:

extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
    if topViewController is MyViewController {
        return topViewController
    } else {
        return nil
    }
}
}
显然,您需要用实现preferredStatusBarStyle的UIViewController子类替换MyViewController

override var preferredStatusBarStyle: UIStatusBarStyle {
    if isBackgroundDark() {
        return .lightContent
    } else {
        return .default
    }
}
同样,isBackgroundDark()由您来实现


最后,每次isBackgroundDark()更改其值时,不要忘记在viewController中调用setNeedsStatusBarAppearanceUpdate()。

多亏了@James Frost,解决方案运行良好
一开始我没有让它工作,所以我想对它做进一步的解释

如果您有UINavigationController的子类, 同时在UINavigationController子类中添加
preferredStatusBarStyle
非常重要

- (UIStatusBarStyle)preferredStatusBarStyle
{
  return UIStatusBarStyleLightContent;
}
并在UINavigationController的扩展中为StatusBarStyle添加
ChildViewController

extension UINavigationController {
  override open var childViewControllerForStatusBarStyle: UIViewController? {
    return visibleViewController
  }
}

顺便说一句,
UINavigationController
子类和UINavigationController的
扩展使用不同的编码语言仍然可以工作。

我尝试了其他解决方案,注意到如果没有
setNeedssStatusBarAppearanceUpdate()
,状态栏不会更新。可以在多个位置调用此标记,但最简单的方法是覆盖
viewControllers
setter

class StatusBarNavigationController: UINavigationController {
    override var childForStatusBarHidden: UIViewController? {
        return topViewController
    }

    override var viewControllers: [UIViewController] {
        didSet { setNeedsStatusBarAppearanceUpdate() }
    }
}

然后,您可以通过编程方式或在故事板上使用
StatusBarNavigationController

您的子视图控制器是否在导航控制器内?@JamesFrost是的。我不确定是否在子类中声明的方法上提供类别(UINavigationController继承UIViewController)方法是一个很好的主意——如果我没有弄错的话,这会导致未定义的行为,因为类别不是适当的重写。因此,我建议改为使用子类化。不过,这是一个很好的答案!(+1)@JamesFrost真是个好建议,我现在开始想办法使用它了。让我试试,稍后再给你回复。非常感谢!(+1)@JamesFrost来自文档:
UINavigationController类实现了一个专门的视图控制器,用于管理分层内容的导航。该类不用于子类化。相反,在希望应用程序的用户界面反映内容层次结构的情况下,您可以使用它的实例。
我认为苹果公司不建议it UINavigationController进行子类化。还有其他方法吗?@Till嗨,看看上面的信息~Hmm。。。我刚刚用一个viewController创建了一个新的Xcode项目。我实现了
preferredStatusBarStyle
以返回
UIStatusBarStyleLightContent
,然后创建了一个包含上述方法的
UINavigationController
类别,它立即起作用。您能否指定“将根视图控制器正确嵌入UINavigationController中”是什么意思?我创建了一个简单的空白项目,目前通过故事板嵌入了一个UIViewController。preferredStatusBarStyle从未被调用。@chourobin你说得对。我上面的回答是误导性的。我之所以让它工作,是因为我碰巧把UINavigationBar设为隐藏状态。在这种情况下,当根本不使用UINavigationController时,它的行为是相同的。@chourobin,当您试图更改UINavigationController堆栈中的UIViewController的StatusBarStyle时。这样做是行不通的。它仅适用于单个UIViewController。WWDC