状态栏的神秘案例

我想要的只是状态栏的两件事:

  • 我希望它默认为白色,因为它会在深色背景上
  • 我希望能够不时地暂时隐藏它。

直截了当吧?

没那么多……让我们看一下这个案例。

因此,如果您四处逛逛,有几种方法可以操纵状态栏,让我们看一下:

在“常规”选项卡中,您可以找到用于项目目标的首选项的两个字段,这些字段用于调整状态栏的默认行为:

  • 状态栏样式-在浅色 (即浅色文本)或默认值 (即深色文本)之间选择
  • 隐藏状态栏-一个复选框。

这些字段是从info plist派生的,这是调整这些字段的另一种方法:

如果您使用info.plist来调整状态栏的默认行为,则需要为以下行添加行:

状态栏最初是隐藏的UIStatusBarHidden

选择

状态栏样式UIStatusBarStyle )。

从以下任一选项中进行选择:

  • 默认UIStatusBarStyleDefault
  • UIStatusBarStyleLightContent

忽略Xcode希望您在不透明黑色样式透明黑色样式(alpha值为0.5)之间进行选择。 这些是不推荐使用的样式,似乎没有人告诉过属性列表编辑器!

如果仔细观察,您会注意到我在info.plist中设置了另一条与状态栏相关的行-另一个名为基于视图控制器的状态栏外观的布尔属性-我将在稍后再讨论这一行。

因此,它们是为状态栏样式设置默认值以及是否将其隐藏的方法。

但是,如果您要临时更改这些默认值,该怎么办?

如果环顾互联网,您会看到提到的两个替代解决方案:

  • UIAppDelegate上设置属性
  • 覆盖视图控制器类中的属性

有些人会建议您在UIAppDelegate上设置属性:

  UIApplication.shared.statusBarStyle = .default //设置样式UIApplication.shared.isStatusBarHidden = false //如果隐藏则设置 

例如,可以在应用程序的UIAppDelegatedidFinishLaunchingWithOptions方法中或在您真正喜欢的任何地方进行设置(例如,如果要临时更改视图控制器的设置,则可以在viewDidAppearviewDidDisappear方法中进行viewDidDisappear

听起来不错,对吧? 只需调用一种方法即可更新状态栏,非常简单。

哦,等等,对不起。 我忘了提一下-iOS 9中已弃用 isStatusBarHidden和statusBarStyle属性。

让我们看一下Xcode建议的视图控制器属性:

在视图控制器类中,您可以覆盖preferredsStatusBarHidden和preferredStatusBarStyle属性:

 覆盖var PreferredsStatusBarHidden:布尔{ 
返回真
}
覆盖var preferredStatusBarStyle:UIStatusBarStyle {
返回.lightContent
}

这些方法默认情况下返回值( prefersStatusBarHidden默认为falsepreferredStatusBarStyle默认为.default ),因此,如果您更改了这些默认值中的任意一个,则当用户导航到另一个视图控制器时(如果新的视图控制器没有自己的实现)在这些方法中,它将恢复为这些默认值。 这与在应用程序委托上设置属性的行为有所不同,后者至少在您明确要求再次更改之前,会在应用程序运行期间更改属性。

更改中视图控制器

顺便说一句,您也可以使用这些属性来更改中间视图控制器。 只需设置一个变量,我们将其称为statusBarHidden ,以包含状态栏的当前首选项。
然后,我们可以在视图控制器属性prefersStatusBarHidden返回此变量:

  var statusBarHidden = true 
覆盖var PreferredsStatusBarHidden:布尔{
返回statusBarHidden
}

现在,如果我们更改statusBarHidden属性,则什么都不会发生。 我们需要告诉系统我们希望状态栏发生变化。 我们可以在属性观察器中执行此操作:

  var statusBarHidden = true { 
didSet(newValue){
setNeedsStatusBarAppearanceUpdate()
}
}

现在,我们应该能够更改statusBarHidden属性,并且状态栏将自动更新。 例如,我们可以有一个按钮来切换状态栏,并连接到IBAction

  @IBAction函数func toggleStatusBar(_ sender:Any){ 
statusBarHidden.toggle()
//如果您是Swift 4.2之前的版本,请使用:
// statusBarHidden =!statusBarHidden
}

因此,让我们总结一下到目前为止更新状态栏的选项:

  • 目标/信息列表字段的常规设置
  • UIAppDelegate上设置属性(不建议使用)
  • 覆盖视图控制器类中的属性

这是尾巴里的毒刺。 还记得我们在信息plist文件中看到的基于视图控制器的状态栏外观属性吗? 我们可以选择哪些选项,取决于我们在此字段中选择的选项。

如果我们将基于View Controller的状态栏外观设置为NO ,则可以在常规设置或信息plist中更改默认状态栏。 我们还可以在UIAppDelegate上设置属性,但不要忘记,这些属性已被弃用。

如果我们将基于View Controller的状态栏外观设置为YES ,则可以覆盖View Controller类中的属性。

还记得我原来的问题吗?

  • “ …默认为白色文本…”-显而易见的方法是在“常规设置” /“Info.plist”中更改默认值
  • “……暂时隐藏……” —这样做的显而易见的方法就是简单地覆盖视图控制器类中的属性。

唯一的问题是,这两个解决方案是互斥的,我无法将基于View控制器的状态栏外观设置NO YES UIAppDelegate上设置属性本来可以很好地解决此问题,但是不建议使用此技术。

剩下的只有我能想到的解决方案。 代替设置状态栏的默认样式,我需要在每个视图控制器上设置状态栏的样式。 有点痛苦! *

*如果有人在将基于View控制器的状态栏外观设置为YES时,想到了在整个项目范围内更改状态栏行为的可靠且安全的方法,我很想听听它!

恐怕我们还无法完成状态栏的神秘处理-将您的View Controller嵌入导航控制器中,如果您将基于View Controller的状态栏外观设置为YES,则导航控制器突然会接管对状态栏的样式以及视图控制器的preferredStatusBarStyle属性将被忽略。

如果要在导航控制器中调整状态栏的样式,则需要在导航栏的style属性中执行此操作,或者使用代码,例如:

 覆盖func viewDidAppear(_动画:布尔){ 
navigationController?.navigationBar.barStyle = .black
}

或在情节提要中:

为了使事情变得极度混乱,例如,如果您希望状态栏带有白色文本,则嵌入导航控制器中的视图控制器将需要请求.lightContent样式(即浅色书写),并且嵌入在导航控制器中的控件将需要请求.black样式(即黑色导航栏)。

不要忘记,如果将基于View控制器的状态栏外观设置为NO ,则对导航栏样式所做的任何更改都将被忽略。

如果基于View Controller的状态栏外观=否:

  • Target / Info.plist字段的常规设置
  • 在AppDelegate上设置属性(不建议使用,请记住)

如果基于View Controller的状态栏外观=是:

  • 覆盖视图控制器类中的属性
  • 设置导航控制器/导航栏的样式。

所以,谜团解决了…… 如果您问我,这一切都不必要地复杂,但是状态栏的状态就在这里!


对使用Swift开发iOS感兴趣? iosdevelopmentwithswift.com上查看 由Manning Publications出版的书籍和视频课程