状态栏的神秘案例
我想要的只是状态栏的两件事:
- 我希望它默认为白色,因为它会在深色背景上
- 我希望能够不时地暂时隐藏它。
直截了当吧?
没那么多……让我们看一下这个案例。
因此,如果您四处逛逛,有几种方法可以操纵状态栏,让我们看一下:
在“常规”选项卡中,您可以找到用于项目目标的首选项的两个字段,这些字段用于调整状态栏的默认行为:
- 状态栏样式-在浅色 (即浅色文本)或默认值 (即深色文本)之间选择
- 隐藏状态栏-一个复选框。
这些字段是从info plist派生的,这是调整这些字段的另一种方法:
如果您使用info.plist来调整状态栏的默认行为,则需要为以下行添加行:
状态栏最初是隐藏的 ( UIStatusBarHidden
)
选择是或否 。
状态栏样式 ( UIStatusBarStyle )。
从以下任一选项中进行选择:
- 默认 (
UIStatusBarStyleDefault
) - 轻 (
UIStatusBarStyleLightContent
)
忽略Xcode希望您在不透明黑色样式和透明黑色样式(alpha值为0.5)之间进行选择。 这些是不推荐使用的样式,似乎没有人告诉过属性列表编辑器!
如果仔细观察,您会注意到我在info.plist中设置了另一条与状态栏相关的行-另一个名为基于视图控制器的状态栏外观的布尔属性-我将在稍后再讨论这一行。
因此,它们是为状态栏样式设置默认值以及是否将其隐藏的方法。
但是,如果您要临时更改这些默认值,该怎么办?
如果环顾互联网,您会看到提到的两个替代解决方案:
- 在
UIAppDelegate
上设置属性 - 覆盖视图控制器类中的属性
有些人会建议您在UIAppDelegate
上设置属性:
UIApplication.shared.statusBarStyle = .default //设置样式UIApplication.shared.isStatusBarHidden = false //如果隐藏则设置
例如,可以在应用程序的UIAppDelegate
的didFinishLaunchingWithOptions
方法中或在您真正喜欢的任何地方进行设置(例如,如果要临时更改视图控制器的设置,则可以在viewDidAppear
和viewDidDisappear
方法中进行viewDidDisappear
。
听起来不错,对吧? 只需调用一种方法即可更新状态栏,非常简单。
哦,等等,对不起。 我忘了提一下-iOS 9中已弃用 isStatusBarHidden和statusBarStyle属性。
让我们看一下Xcode建议的视图控制器属性:
在视图控制器类中,您可以覆盖preferredsStatusBarHidden和preferredStatusBarStyle属性:
覆盖var PreferredsStatusBarHidden:布尔{
返回真
}
覆盖var preferredStatusBarStyle:UIStatusBarStyle {
返回.lightContent
}
这些方法默认情况下返回值( prefersStatusBarHidden
默认为false
, preferredStatusBarStyle
默认为.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出版的书籍和视频课程 。