UIStatusBarStyle PreferredStatusBarStyle在iOS 7上不起作用

在我的iPhone应用程序构build与Xcode 5的iOS 7我设置UIViewControllerBasedStatusBarAppearance=YESinfo.plist ,并在我的ViewController我有这样的代码:

 -(UIStatusBarStyle) preferredStatusBarStyle { return UIStatusBarStyleLightContent; } 

但是状态栏在黑色背景下仍然是黑色的。

我知道可以通过在info.plist设置UIViewControllerBasedStatusBarAppearance=NO来改变这个应用程序的范围,但是我实际上需要在运行时通过viewController基础来改变viewController

我发现,如果你的ViewController是在一个navigationController里面,那么navigationController的navigationBar.barStyle决定了statusBarStyle。

将导航条的barStyle设置为UIBarStyleBlackTranslucent会给出白色的状态栏文本(即UIStatusBarStyleLightContent ),而UIBarStyleDefault会给出黑色的状态栏文本(即UIStatusBarStyleDefault )。

请注意 ,即使您通过barTintColor完全更改navigationBar的颜色,也barTintColor

好的,这是诀窍。 您必须添加键“查看基于控制器的状态栏”,并将值设置为否。

这与此键的含义相反,但即使将该值设置为No ,仍然可以更改状态栏的外观以及是否显示在任何视图控制器中。 所以它的行为是“是”,但是设置为“否”!

现在我可以得到状态栏白色或黑暗。

我可能会迟到一点,但是别的什么人都在寻找一个工作和validation的应用程序广泛的解决scheme。

@mxcl在描述发生这种情况时是正确的。 为了纠正它,我们只需创build一个覆盖UINavigationController的preferredSatusBarStyle()方法的扩展(或obj-c中的类别)。 这是Swift中的一个例子:

 extension UINavigationController { public override func preferredStatusBarStyle() -> UIStatusBarStyle { if let rootViewController = self.viewControllers.first { return rootViewController.preferredStatusBarStyle() } return super.preferredStatusBarStyle() } } 

这段代码简单地提取第一个视图控制器(根视图控制器)并解开它(obj-c只是检查它不是零)。 如果解包成功(而不是零),那么我们抓住rootViewControllers preferredStatusBarStyle。 否则,我们只是返回默认值。

希望这可以帮助任何人可能需要它。

对于preferredStatusBarStyle()UINavigationControllerUITabBarController工作,我添加下面的代码,它将从当前可见的视图控制器中获得首选的状态栏样式。

 extension UITabBarController { public override func childViewControllerForStatusBarStyle() -> UIViewController? { return selectedViewController } } extension UINavigationController { public override func childViewControllerForStatusBarStyle() -> UIViewController? { return visibleViewController } } 

对于Swift 3来说,这些不是方法,而是属性:

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

为了在接受的答案中提供更多的细节,在你的应用程序委托的didFinishLaunchingWithOptions:方法中放入以下行:

 [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; 

然后,在Info.plist中,添加View controller-based status bar appearance ,并将其设置为NO

我相信这是应该如何做,而不是从导航控制器,如果你想为整个应用程序相同的状态栏颜色。 你可能有不一定embedded到UINavigationController屏幕,或者其他地方的不同的UINavigationController子类以及其他东西。

编辑 :你也可以做到这一点,而无需键入任何代码: https : //stackoverflow.com/a/18732865/855680

在viewDidLoad中只写这个

 [self setNeedsStatusBarAppearanceUpdate]; 

只要这样做,它会工作

你可以试试这个吗?

 Set UIViewControllerBasedStatusBarAppearance to NO. Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; 

还有一件事我看到你的问题,你已经写了这样的方法

  -(void)UIStatusBarStyle PreferredStatusBarStyle () { return UIStatusBarStyle.LightContent; } 

但应该是这样的

 -(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleLightContent; } 

这是我如何解决它。 通常navigationController或tabBarController是决定状态栏的外观(隐藏,颜色等)。

所以我结束了inheritance导航控制器和覆盖preferredStatusBarStyle。 如果当前可见的ViewContorller实现了StatusBarStyleHandler,我要求将该值用作样式,如果不是,我只是返回一个默认值。

触发状态栏外观更新的方法是调用setNeedsStatusBarAppearanceUpdate ,它将再次触发preferredStatusBarStyle ,并根据方法返回的内容更新UI

 public protocol StatusBarStyleHandler { var preferredStatusBarStyle: UIStatusBarStyle { get } } public class CustomNavigationCotnroller: UINavigationController { public override var preferredStatusBarStyle: UIStatusBarStyle { if let statusBarHandler = visibleViewController as? StatusBarStyleHandler { return statusBarHandler.preferredStatusBarStyle } return .default } } 

然后用法

 public class SomeController: UIViewController, StatusBarStyleHandler { private var statusBarToggle = true // just a sample for toggling the status bar style each time method is called private func toggleStatusBarColor() { statusBarToggle = !statusBarToggle setNeedsStatusBarAppearanceUpdate() } public override var preferredStatusBarStyle: UIStatusBarStyle { return statusBarToggle ? .lightContent : .default } } 

1)整个项目的一个设置:

如果可用,请从您的info.plist中移除UIViewControllerBasedStatusBarAppearance键值对,或者将其设置为NO而不移除它。 如果它不在你的info.plist中,请不要做任何事情。 该属性的默认值是NO

将以下代码添加到您的AppDelegate.m中:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; } 

2)不同视图控制器的不同设置:

UIViewControllerBasedStatusBarAppearance键值对添加到您的info.plist并将其设置为YES

如果View Controller未embedded到导航控制器中。 我们说MyViewController。 只需将下面的代码添加到您的MyViewController.m文件。 如果您的View Controllerembedded到导航控制器中,请创build一个新的Cocoa Touch类并将其设置为UINavigationController的子类。 比方说,MyNC。 在右侧窗格的“故事板”上select“导航控制器视图”; 实用程序 – >身份检查器 – >自定义类 – >类,键入“MyNC”。 链接Storyboard视图和你的“MyNC”Cocoa Touch Class之后,将下面的代码添加到你的MyNC.m中:

 - (BOOL)prefersStatusBarHidden { return NO; } -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } 

如果想要在splashScreen中隐藏statusBar,但想要将样式更改为浅色内容(Plist上的StatusBarInitiallyHidden必须为NO才能隐藏状态栏),则可以将此添加到appDelegate的didFinishLaunchingWithOptions方法以更改为lightContent。

 [[UIApplication sharedApplication]setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]; 

迅速的例子

在AppDelegate.swift中

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent; return true } 

在info.plist中查看基于控制器的状态栏外观:NO

如果您正在使用NavigationController ,则可以inheritanceNavigationController以便查阅其子视图控制器

// MyCustomNavigationController

 - (NSUInteger)supportedInterfaceOrientations { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk supportedInterfaceOrientations]; } - (BOOL)shouldAutorotate { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk shouldAutorotate]; } - (UIStatusBarStyle)preferredStatusBarStyle { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk preferredStatusBarStyle]; } - (UIViewController *)findChildVC { return self.viewControllers.firstObject; } 

即使在这里所有的答案,我仍然没有find确切的解决scheme,但从丹尼尔的答案开始。 结果是:

 override var preferredStatusBarStyle: UIStatusBarStyle { return visibleViewController?.preferredStatusBarStyle ?? .lightContent } 

在导航控制器(类似的选项卡,只是selectedViewController)。 然后它会尊重:

 override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } 

在每个视图控制器中,除非您另行设置。 我不需要在任何地方调用setNeedsStatusBarAppearanceUpdate() ,它只是当你到达每个视图控制器时更新。

您可以设置状态栏的样式。 它将类似IOS 6和以下的状态栏。
将这些方法粘贴到视图控制器中

 -(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleBlackOpaque; } 

并从视图调用这个方法加载这样的

 if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) { [self setNeedsStatusBarAppearanceUpdate]; } 

对于swift 3,在你的UIViewController中:

 override var preferredStatusBarStyle : UIStatusBarStyle { return UIStatusBarStyle.lightContent }