25

我的导航栏有一个white backgroundColor,我的状态栏使用dark textColor. 当用户将 iOS 主题更改为深色模式时,状态栏将变为背景white上的文本。white结果,我什么都看不见。如何为我的应用禁用此更改?

4

9 回答 9

45

iOS 13 解决方案

UINavigationController是 的子类UIViewController!(谁知道 )

因此,当呈现嵌入在导航控制器中的视图控制器时,您并没有真正呈现嵌入的视图控制器。您正在展示导航控制器!UINavigationController, 作为 , 的子类UIViewController, 继承preferredStatusBarStylechildForStatusBarStyle, 您可以根据需要进行设置。

以下任何一种方法都应该有效:

  1. 完全退出黑暗模式

    • 在您的info.plist中,添加以下属性:
      • 键 - UIUserInterfaceStyle(又名“用户界面风格”)
      • 价值 - 光
  2. 覆盖preferredStatusBarStyle范围内UINavigationController

    • preferredStatusBarStyle( doc ) - 视图控制器的首选状态栏样式

    • 子类或扩展 UINavigationController

        class MyNavigationController: UINavigationController {
            override var preferredStatusBarStyle: UIStatusBarStyle {
                .lightContent
            }
        }
      

      或者

        extension UINavigationController {
            open override var preferredStatusBarStyle: UIStatusBarStyle {
                .lightContent
            }
        }
      
  3. 覆盖childForStatusBarStyle范围内UINavigationController

    • childForStatusBarStyle( doc ) - 当系统需要视图控制器用于确定状态栏样式时调用
    • 根据苹果的文档,

    “如果您的容器视图控制器从其子视图控制器之一派生其状态栏样式,[覆盖此属性]并返回该子视图控制器。如果您返回 nil 或不覆盖此方法,则使用 self 的状态栏样式. 如果此方法的返回值发生变化,请调用 setNeedsStatusBarAppearanceUpdate() 方法。"

    • 换句话说,如果您在此处不执行解决方案 3,系统将回退到上面的解决方案 2。

    • 子类或扩展 UINavigationController

        class MyNavigationController: UINavigationController {
            override var childForStatusBarStyle: UIViewController? {
                topViewController
            }
        }
      

      或者

        extension UINavigationController {    
            open override var childForStatusBarStyle: UIViewController? {
                topViewController
            }
        }
      
    • 您可以在上面返回您想要的任何视图控制器。我推荐以下之一:

      • topViewController(of UINavigationController) ( doc ) - 位于导航堆栈顶部的视图控制器
      • visibleViewController(of UINavigationController) ( doc ) - 与导航界面中当前可见视图相关联的视图控制器(提示:这可以包括“以模态方式呈现在导航控制器本身之上的视图控制器”)

注意:如果您决定子类UINavigationController化,请记住通过 IB 中的身份检查器将该类应用于您的导航控制器。

编辑:删除线编辑已删除扩展作为建议的答案。其他开发人员指出,他们停止在 Xcode 11.4 中工作,Apple 的文档不鼓励使用这种模棱两可的行为。

PS 我的代码使用 Swift 5.1 语法

于 2019-10-23T03:05:52.557 回答
15

如果您将UIViewControllerBasedStatusBarAppearance应用程序中的键设置info.plistYES,则可以覆盖当前呈现的视图控制器中的状态栏样式:

override var preferredStatusBarStyle: UIStatusBarStyle {
    if #available(iOS 13, *) {
        return .darkContent
    } else {
        return .default
    }
}

并调用 setNeedsStatusBarAppearanceUpdate() 方法

于 2019-08-16T06:38:28.510 回答
6

您可以将扩展名写入UIStatusBarStyle

extension UIStatusBarStyle {
    static var black: UIStatusBarStyle {
        if #available(iOS 13.0, *) {
            return .darkContent
        }
        return .default
    }
}

然后您可以轻松地在您的 ViewControllers 中使用:

override var preferredStatusBarStyle: UIStatusBarStyle {
    .black
}
于 2019-10-04T14:39:24.773 回答
4

您可以尝试使您的导航栏始终light

if #available(iOS 13.0, *) {
    navigationController?.navigationBar.overrideUserInterfaceStyle = .light
 }
于 2019-10-09T07:35:06.470 回答
1

我做过这样的事情。

我有切换器功能,根据显示的视图控制器切换状态栏样式

func toggleLight() {
        self.navigationBar.barTintColor = AppColors.White

        isDarkStyle = false
        setNeedsStatusBarAppearanceUpdate()

    }

这是最重要的部分

override var preferredStatusBarStyle: UIStatusBarStyle {

        if #available(iOS 13.0, *) {
            return isDarkStyle ? .lightContent : .darkContent
        }
        return isDarkStyle ? .lightContent : .default
    }

其中 isDarkStyle 代表导航栏背景颜色深或浅。如果它是暗的,那么文本(内容)应该是亮的,如果它是亮的,那么文本(内容)应该是默认的或者从 iOS 13 开始是暗的。

总结一下:.lightContent, .darkContent显示独立于暗模式,就像它应该做的那样。虽然.default容易受到暗模式更改的影响!

于 2019-10-24T09:11:40.477 回答
0

如果您使用 aUINavigationControllerpreferredStatusBarStyle请像这样覆盖扩展(或您自己的子类)中的 (仅preferredStatusBarStyle在您的视图控制器中覆盖是行不通的):

extension UINavigationController {
  override open var preferredStatusBarStyle: UIStatusBarStyle {
    guard #available(iOS 13, *) else {
      return .default
    }
    return .darkContent
  }
}

正如弗兰克所说,UIViewControllerBasedStatusBarAppearance必须YES在你的info.plist

于 2019-10-08T17:54:06.170 回答
0

此扩展可帮助您更改状态栏文本颜色并支持 iOS 13 https://stackoverflow.com/a/59767435/10512612

于 2020-01-16T10:21:07.840 回答
0

如果其他人发现上述答案都不起作用(就像我所做的那样),那么如果您在UIWindowScene其中有多个窗口,它将使用最顶部的窗口而不是关键窗口来确定状态栏的外观,则存在一个非常具体的边缘情况。

因此,例如,如果您的键窗口windowLevel设置为 to1和辅助窗口windowLevel设置为1.1,UIKit 将(无论出于何种原因)询问辅助窗口中的视图控制器的状态栏外观,而不是键中的视图控制器窗口,即使它的 alpha 为 0

我们的解决方法是仅在辅助窗口处于活动状态时将其置于较高级别,并在其隐藏时将其降低到关键窗口下方。

于 2021-08-04T12:17:17.953 回答
0

有两种方法可以解决这个问题。在 UINavigationController 后代类中定义 childViewControllerForStatusBarStyle 函数:

@interface MyNavigationController : UINavigationController
...
@end

@implementation MyNavigationController
...
- (UIViewController *)childViewControllerForStatusBarStyle
{
    return self.topViewController;
}
...
@end

之后,您需要为每个控制器添加函数 preferredStatusBarStyle。

第二个选项是为所有控制器定义 preferredStatusBarStyle 函数。但是这个函数不应该位于根控制器中,而应该位于 UINavigationController 的后代类中。

@interface MyNavigationController : UINavigationController
...
@end

@implementation MyNavigationController
...
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}
...
@end

但是,即使在这种情况下,也有必要为所有隐藏导航栏的控制器(如果有)定义函数 preferredStatusBarStyle。

于 2019-10-15T16:45:53.350 回答