preferredStatusBarStyle不被调用

我跟着这个线程来覆盖-preferredStatusBarStyle ,但它不被调用。 有什么select,我可以改变启用它? (我在我的项目中使用XIB。)

可能的根本原因

我有同样的问题,并发现这是因为我没有在我的应用程序窗口中设置根视图控制器。

我在其中实现了preferredStatusBarStyleUIViewControllerUITabBarController ,它控制了屏幕上的视图的外观。

当我设置根视图控制器指向此UITabBarController ,状态栏更改开始正常工作,并按预期方式(并调用preferredStatusBarStyle方法)。

 (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // other view controller loading/setup code self.window.rootViewController = rootTabBarController; [self.window makeKeyAndVisible]; return YES; } 

替代方法(在iOS 9中弃用)

或者,您可以根据自己的背景颜色,在每个视图控制器中根据需要调用以下其中一种方法,而不必使用setNeedsStatusBarAppearanceUpdate

 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; 

要么

 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; 

请注意,如果使用此方法,则还需要在plist文件中将UIViewControllerBasedStatusBarAppearance设置为NO

对于任何使用UINavigationController的人:

UINavigationController不会将preferredStatusBarStyle调用转发到其子视图控制器。 相反,它pipe理着自己的状态,因为它应该在状态栏所在的屏幕顶部绘制,所以应该对它负责。 因此,在导航控制器内的VC中实现preferredStatusBarStyle将不会执行任何操作 – 它们将永远不会被调用。

窍门是UINavigationController用来决定返回什么UIStatusBarStyleDefaultUIStatusBarStyleLightContent 。 它基于它的UINavigationBar.barStyle 。 默认( UIBarStyleDefault )导致在黑暗的前景UIStatusBarStyleDefault状态栏。 而UIBarStyleBlack将会提供一个UIStatusBarStyleLightContent状态栏。

TL; DR:

如果您想在UINavigationController使用UIStatusBarStyleLightContent ,请使用:

 self.navigationController.navigationBar.barStyle = UIBarStyleBlack; 

所以我实际上添加了一个类别到UINavigationController,但使用的方法:

 -(UIViewController *)childViewControllerForStatusBarStyle; -(UIViewController *)childViewControllerForStatusBarHidden; 

并有那些返回当前可见的UIViewController。 这让当前的可见视图控制器设置自己的首选风格/可见性。

这是一个完整的代码片段:

在Swift中:

 extension UINavigationController { public override func childViewControllerForStatusBarHidden() -> UIViewController? { return self.topViewController } public override func childViewControllerForStatusBarStyle() -> UIViewController? { return self.topViewController } } 

在Objective-C中:

 @interface UINavigationController (StatusBarStyle) @end @implementation UINavigationController (StatusBarStyle) -(UIViewController *)childViewControllerForStatusBarStyle { return self.topViewController; } -(UIViewController *)childViewControllerForStatusBarHidden { return self.topViewController; } @end 

为了好的措施,下面是在UIViewController中实现的方法:

在Swift中

 override public func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func prefersStatusBarHidden() -> Bool { return false } 

在Objective-C中

 -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; // your own style } - (BOOL)prefersStatusBarHidden { return NO; // your own visibility code } 

最后,请确保您的应用程序plist没有将“基于视图控制器的状态栏外观”设置为NO。 删除该行或将其设置为YES(我相信这是iOS 7的默认设置?)

泰森的答案是正确的在UINavigationController中将状态栏颜色更改为白色。

如果有人希望通过在AppDelegate编写代码来完成相同的结果,那么使用下面的代码并将其写入AppDelegate's didFinishLaunchingWithOptions方法中。

不要忘记在.plist文件中将UIViewControllerBasedStatusBarAppearance设置为YES ,否则更改将不会反映出来。

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // status bar appearance code [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]; return YES; } 

对于还在为此而苦恼的人,这个简单的扩展应该可以解决你的问题。

 extension UINavigationController { override open var childViewControllerForStatusBarStyle: UIViewController? { return self.topViewController } } 

除了Hippo的答案:如果您使用的是UINavigationController,那么最好添加一个类别:

 // UINavigationController+StatusBarStyle.h: @interface UINavigationController (StatusBarStyle) @end // UINavigationController+StatusBarStyle.m: @implementation UINavigationController (StatusBarStyle) - (UIStatusBarStyle)preferredStatusBarStyle { //also you may add any fancy condition-based code here return UIStatusBarStyleLightContent; } @end 

该解决scheme可能比切换到即将被弃用的行为更好。

如果你的viewController在UINavigationController下。

子类UINavigationController并添加

 override var preferredStatusBarStyle: UIStatusBarStyle { return topViewController?.preferredStatusBarStyle ?? .default } 

ViewController的preferredStatusBarStyle将被调用。

UIStatusBarStyle在iOS 7中

iOS 7中的状态栏是透明的,它后面的视图显示了通过。

状态栏的风格是指其内容的外观。 在iOS 7中,状态栏内容可能是黑暗的( UIStatusBarStyleDefault )或亮的( UIStatusBarStyleLightContent )。 UIStatusBarStyleBlackTranslucentUIStatusBarStyleBlackOpaque都在iOS 7.0中被弃用。 改用UIStatusBarStyleLightContent

如何更改UIStatusBarStyle

如果下面的状态栏是一个导航栏,状态栏风格将被调整为与导航栏风格( UINavigationBar.barStyle )相匹配:

具体而言,如果导航栏风格是UIBarStyleDefault,则状态栏风格将为UIStatusBarStyleDefault ; 如果导航栏风格是UIBarStyleBlack ,则状态栏风格将是UIStatusBarStyleLightContent

如果状态栏下方没有导航栏,则应用程序运行时,可以通过单独的视图控制器来控制和更改状态栏的样式。

[UIViewController preferredStatusBarStyle]是在iOS 7中添加的新方法。可以覆盖返回首选状态栏样式:

 - (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } 

如果状态栏风格应该由子视图控制器而不是自我控制,则覆盖-[UIViewController childViewControllerForStatusBarStyle]返回该子视图控制器。

如果您更愿意select退出此行为,并使用-[UIApplication statusBarStyle]方法设置状态栏样式,请将UIViewControllerBasedStatusBarAppearance关键点添加到应用程序的Info.plist文件中,并将其值设置为NO。

上面的答案对于UINavigationControllers来说仍然是一个很好的答案 。 不过,对于swift 3,childViewController函数已经改变为vars 。 所以UINavigationController扩展代码应该是:

 override open var childViewControllerForStatusBarStyle: UIViewController? { return topViewController } override open var childViewControllerForStatusBarHidden: UIViewController? { return topViewController } 

然后在视图控制器应该指定状态栏的风格:

 override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } 

Swift 3 iOS 10解决scheme:

 override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } 

如果有人正在使用导航控制器,并希望所有的导航控制器都具有黑色风格,那么可以在Swift 3中这样写一个扩展到UINavigationController,它将应用于所有导航控制器(而不是将其分配给一个控制器时间)。

 extension UINavigationController { override open func viewDidLoad() { super.viewDidLoad() self.navigationBar.barStyle = UIBarStyle.black } } 

这是我解决这个问题的方法。

定义一个名为AGViewControllerAppearance的协议。

AGViewControllerAppearance.h

 #import <Foundation/Foundation.h> @protocol AGViewControllerAppearance <NSObject> @optional - (BOOL)showsStatusBar; - (BOOL)animatesStatusBarVisibility; - (UIStatusBarStyle)preferredStatusBarStyle; - (UIStatusBarAnimation)prefferedStatusBarAnimation; @end 

UIViewController上定义一个名为Upgrade的类别。

的UIViewController + Upgrade.h

 #import <UIKit/UIKit.h> @interface UIViewController (Upgrade) // // Replacements // - (void)upgradedViewWillAppear:(BOOL)animated; @end 

的UIViewController + Upgrade.m

 #import "UIViewController+Upgrade.h" #import <objc/runtime.h> #import "AGViewControllerAppearance.h" // This is the appearance protocol @implementation UIViewController (Upgrade) + (void)load { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wselector" Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:)); #pragma clang diagnostic pop Method upgradedViewWillAppear = class_getInstanceMethod(self, @selector(upgradedViewWillAppear:)); method_exchangeImplementations(viewWillAppear, upgradedViewWillAppear); } #pragma mark - Implementation - (void)upgradedViewWillAppear:(BOOL)animated { // // Call the original message (it may be a little confusing that we're // calling the 'same' method, but we're actually calling the original one :) ) // [self upgradedViewWillAppear:animated]; // // Implementation // if ([self conformsToProtocol:@protocol(AGViewControllerAppearance)]) { UIViewController <AGViewControllerAppearance> *viewControllerConformingToAppearance = (UIViewController <AGViewControllerAppearance> *)self; // // Status bar // if ([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)]) { BOOL shouldAnimate = YES; if ([viewControllerConformingToAppearance respondsToSelector:@selector(animatesStatusBarVisibility)]) { shouldAnimate = [viewControllerConformingToAppearance animatesStatusBarVisibility]; } [[UIApplication sharedApplication] setStatusBarStyle:[viewControllerConformingToAppearance preferredStatusBarStyle] animated:shouldAnimate]; } if ([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)]) { UIStatusBarAnimation animation = UIStatusBarAnimationSlide; if ([viewControllerConformingToAppearance respondsToSelector:@selector(prefferedStatusBarAnimation)]) { animation = [viewControllerConformingToAppearance prefferedStatusBarAnimation]; } [[UIApplication sharedApplication] setStatusBarHidden:(! [viewControllerConformingToAppearance showsStatusBar]) withAnimation:animation]; } } } @end 

现在,该说视图控制器正在实现AGViewControllerAppearance协议。

例:

 @interface XYSampleViewController () <AGViewControllerAppearance> ... the rest of the interface @end 

当然,你可以从协议中实现其余的方法( showsStatusBaranimatesStatusBarVisibilityprefferedStatusBarAnimation ), UIViewController + Upgrade将根据它们提供的值进行适当的定制。

如果有人遇到这个问题与UISearchController。 只要创build一个UISearchController的新子类,然后将下面的代码添加到该类中:

 override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } 

在任何一种UIViewController的Swift中:

在你的AppDelegate设置:

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { window!.rootViewController = myRootController return true } 

myRootController可以是任何types的UIViewController ,例如UITabBarControllerUINavigationController

然后,像这样覆盖这个根控制器:

 class RootController: UIViewController { override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } } 

这将改变整个应用程序状态栏的外观,因为根控制器是唯一负责状态栏的外观。

请记住在Info.plist中将View controller-based status bar appearance为YES以使其工作(这是默认设置)。

在UINavigationController上, preferredStatusBarStyle不被调用,因为它的topViewControllerselftopViewController 。 所以,为了获得在UINavigationController上调用的preferredStatusBarStyle ,你需要改变它的childViewControllerForStatusBarStyle

做一个UINavigationController(我的build议):

 class MyRootNavigationController: UINavigationController { override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func childViewControllerForStatusBarStyle() -> UIViewController? { return nil } } 

为所有UINavigationController(警告:它影响UIDocumentPickerViewController,UIImagePickerController等)做到这一点:

 extension UINavigationController { public override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } public override func childViewControllerForStatusBarStyle() -> UIViewController? { return nil } } 

NavigationController或TabBarController是需要提供样式的。 这是我解决的方法: https : //stackoverflow.com/a/39072526/242769

注意当使用self.navigationController.navigationBar.barStyle = UIBarStyleBlack;

一定要去你的plist,并将“查看基于控制器的状态栏外观”设置为YES。 如果它不,它将无法正常工作。