我遵循这个线程重写-preferredStatusBarStyle,但它没有被调用。 有什么选项我可以改变来启用它吗?(我在我的项目中使用xib。)


当前回答

从Xcode 11.4开始,覆盖UINavigationController扩展中的preferredStatusBarStyle属性不再有效,因为它将不会被调用。

将navigationBar的barStyle设置为.black确实有效,但如果你向navigationBar添加子视图,它可能在明暗模式下具有不同的外观,则会添加不必要的副作用。因为通过将barStyle设置为黑色,嵌入在navigationBar中的视图的userInterfaceStyle将始终具有userInterfaceStyle。不管应用程序的userinterfacstyle是暗的。

我提出的正确解决方案是通过添加UINavigationController的子类并覆盖preferredStatusBarStyle。如果你使用这个自定义的UINavigationController为你所有的视图,你将在保存侧。

其他回答

Tyson的答案是正确的改变状态栏颜色为白色在UINavigationController。

如果有人想通过在AppDelegate中编写代码来实现相同的结果,那么请使用下面的代码并在AppDelegate的didFinishLaunchingWithOptions方法中编写它。

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

Code

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

     return YES;
}

Swift 4.2及以上版本

正如所选答案中提到的,根本原因是检查您的窗口根视图控制器对象。

流结构的可能情况

Custom UIViewController object is window root view controller Your window root view controller is a UIViewController object and it further adds or removes navigation controller or tabController based on your application flow. This kind of flow is usually used if your app has pre login flow on navigation stack without tabs and post login flow with tabs and possibly every tab further holds navigation controller. TabBarController object is window root view controller This is the flow where window root view controller is tabBarController possibly every tab further holds navigation controller. NavigationController object is window root view controller This is the flow where window root view controller is navigationController. I am not sure if there is any possibility to add tab bar controller or new navigation controller in an existing navigation controller. But if there is such case, we need to pass the status bar style control to the next container. So, I added the same check in UINavigationController extension to find childForStatusBarStyle

使用以下扩展,它处理所有上述场景-

extension UITabBarController {
    open override var childForStatusBarStyle: UIViewController? {
        return selectedViewController?.childForStatusBarStyle ?? selectedViewController
    }
}

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

extension AppRootViewController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return children.first { $0.childForStatusBarStyle != nil }?.childForStatusBarStyle?.preferredStatusBarStyle ?? .default
    }
}

在info中你不需要UIViewControllerBasedStatusBarAppearance键。Plist默认为true

对于更复杂的流程,需要考虑的要点

In case you present new flow modally, it detaches from the existing status bar style flow. So, suppose you are presenting a NewFlowUIViewController and then add new navigation or tabBar controller to NewFlowUIViewController, then add extension of NewFlowUIViewController as well to manage further view controller's status bar style. In case you set modalPresentationStyle other than fullScreen while presenting modally, you must set modalPresentationCapturesStatusBarAppearance to true so that presented view controller must receive status bar appearance control.

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

extension UINavigationController {

    override open func viewDidLoad() {
        super.viewDidLoad()

        self.navigationBar.barStyle = UIBarStyle.black
    }

}

可能的根本原因

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

我在UIViewController中实现了preferredStatusBarStyle,在UITabBarController中使用,它控制了屏幕上视图的外观。

当我设置根视图控制器指向这个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];

or

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];

注意,如果你使用这个方法,你还需要在plist文件中将UIViewControllerBasedStatusBarAppearance设置为NO。

Swift 3 iOS 10解决方案:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
 }