我遵循这个线程重写-preferredStatusBarStyle,但它没有被调用。 有什么选项我可以改变来启用它吗?(我在我的项目中使用xib。)
当前回答
在我的例子中,我意外地将视图/导航控制器呈现为UIModalPresentationStyle。overFullScreen,这导致preferredStatusBarStyle没有被调用。切换回UIModalPresentationStyle后。全屏,一切正常。
其他回答
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.
可能的根本原因
我也遇到了同样的问题,我发现这是因为我没有在我的应用程序窗口中设置根视图控制器。
我在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。
对于任何使用UINavigationController的人:
UINavigationController不会转发preferredStatusBarStyle调用给它的子视图控制器。相反,它管理自己的状态——就像它应该做的那样,它在屏幕顶部绘制状态栏,因此应该对状态栏负责。因此,在导航控制器中实现preferredStatusBarStyle在vc中什么都不会做——它们永远不会被调用。
诀窍是UINavigationController使用什么来决定UIStatusBarStyleDefault或uistatusbarstyelightcontent返回什么。它基于它的UINavigationBar.barStyle。默认的(UIBarStyleDefault)导致前景UIStatusBarStyleDefault状态栏为黑色。UIBarStyleBlack会给出一个uistatusbarstyelightcontent状态栏。
TL; diana:
如果你想在UINavigationController上使用UIStatusBarStyleLightContent:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
我的应用程序使用了所有三个:UINavigationController, UISplitViewController, UITabBarController,因此这些似乎都接管了对状态栏的控制,并将导致preferedStatusBarStyle不为他们的孩子被调用。要覆盖此行为,您可以创建一个扩展,就像前面提到的其他答案一样。这是一个扩展,这三个,在Swift 4。希望苹果对这类事情能更清楚些。
extension UINavigationController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
extension UISplitViewController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
编辑:针对Swift 4.2 API更改的更新
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
extension UISplitViewController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
Swift 3 iOS 10解决方案:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
推荐文章
- 更改UITextField和UITextView光标/插入符颜色
- 'Project Name'是通过优化编译的——步进可能会表现得很奇怪;变量可能不可用
- 如何设置回退按钮文本在Swift
- 模拟器慢动作动画现在打开了吗?
- 如何为TableView创建NSIndexPath
- 滑动删除和“更多”按钮(就像iOS 7的邮件应用程序)
- 使UINavigationBar透明
- 如何改变推和弹出动画在一个基于导航的应用程序
- 删除/重置核心数据中的所有条目?
- setNeedsLayout vs. setNeedsUpdateConstraints和layoutIfNeeded vs. updateConstraintsIfNeeded
- 不区分大小写的比较
- 我怎么能得到一个uiimage的高度和宽度?
- 我如何模仿地图应用程序的底部表格?
- 改变导航栏后退按钮的颜色
- iOS应用程序“应用程序无法验证”只在一台设备上