ios 未调用 preferredStatusBarStyle
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19022210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
preferredStatusBarStyle isn't called
提问by trgoofi
I followed this threadto override -preferredStatusBarStyle
, but it isn't called.
Are there any options that I can change to enable it? (I'm using XIBs in my project.)
我按照这个线程来覆盖-preferredStatusBarStyle
,但它没有被调用。是否有任何选项可以更改以启用它?(我在我的项目中使用 XIB。)
采纳答案by AbdullahC
Possible root cause
可能的根本原因
I had the same problem, and figured out it was happening because I wasn't setting the root view controller in my application window.
我遇到了同样的问题,并发现它正在发生,因为我没有在我的应用程序窗口中设置根视图控制器。
The UIViewController
in which I had implemented the preferredStatusBarStyle
was used in a UITabBarController
, which controlled the appearance of the views on the screen.
的UIViewController
,其中我已经实现的preferredStatusBarStyle
是在一个使用UITabBarController
,其控制的屏幕上的意见的外观。
When I set the root view controller to point to this UITabBarController
, the status bar changes started to work correctly, as expected (and the preferredStatusBarStyle
method was getting called).
当我将根视图控制器设置为指向 this 时UITabBarController
,状态栏更改开始按预期正常工作(并且该preferredStatusBarStyle
方法被调用)。
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
... // other view controller loading/setup code
self.window.rootViewController = rootTabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Alternative method (Deprecated in iOS 9)
替代方法(在 iOS 9 中已弃用)
Alternatively, you can call one of the following methods, as appropriate, in each of your view controllers, depending on its background color, instead of having to use setNeedsStatusBarAppearanceUpdate
:
或者,您可以根据背景颜色在每个视图控制器中调用以下方法之一,而不必使用setNeedsStatusBarAppearanceUpdate
:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
or
或者
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
Note that you'll also need to set UIViewControllerBasedStatusBarAppearance
to NO
in the plist file if you use this method.
请注意,如果您使用此方法,您还需要在 plist 文件中设置UIViewControllerBasedStatusBarAppearance
为NO
。
回答by Tyson
For anyone using a UINavigationController:
对于使用 UINavigationController 的任何人:
The UINavigationController
does not forward on preferredStatusBarStyle
calls to its child view controllers. Instead it manages its own state - as it should, it is drawing at the top of the screen where the status bar lives and so should be responsible for it. Therefor implementing preferredStatusBarStyle
in your VCs within a nav controller will do nothing - they will never be called.
该UINavigationController
不转发就preferredStatusBarStyle
调用它的子视图控制器。相反,它管理自己的状态——它应该在屏幕顶部绘制状态栏所在的位置,因此应该对其负责。因此preferredStatusBarStyle
,在导航控制器中的 VC 中实现将什么也不做——它们永远不会被调用。
The trick is what the UINavigationController
uses to decide what to return for UIStatusBarStyleDefault
or UIStatusBarStyleLightContent
. It bases this on its UINavigationBar.barStyle
. The default (UIBarStyleDefault
) results in the dark foreground UIStatusBarStyleDefault
status bar. And UIBarStyleBlack
will give a UIStatusBarStyleLightContent
status bar.
诀窍是用什么UINavigationController
来决定返回什么UIStatusBarStyleDefault
或UIStatusBarStyleLightContent
。它基于其UINavigationBar.barStyle
. 默认 ( UIBarStyleDefault
) 导致前景UIStatusBarStyleDefault
状态栏变暗。并且UIBarStyleBlack
会给出一个UIStatusBarStyleLightContent
状态栏。
TL;DR:
特尔;博士:
If you want UIStatusBarStyleLightContent
on a UINavigationController
use:
如果你想UIStatusBarStyleLightContent
在UINavigationController
使用:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
回答by serenn
So I actually added a category to UINavigationController but used the methods:
所以我实际上向 UINavigationController 添加了一个类别,但使用了以下方法:
-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;
and had those return the current visible UIViewController. That lets the current visible view controller set its own preferred style/visibility.
并让那些返回当前可见的 UIViewController。这让当前可见视图控制器设置自己的首选样式/可见性。
Here's a complete code snippet for it:
这是它的完整代码片段:
In Swift:
在斯威夫特:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
In Objective-C:
在 Objective-C 中:
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
And for good measure, here's how it's implemented then in a UIViewController:
为了更好的衡量,以下是它在 UIViewController 中的实现方式:
In Swift
在斯威夫特
override public func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
override func prefersStatusBarHidden() -> Bool {
return false
}
In Objective-C
在 Objective-C 中
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // your own style
}
- (BOOL)prefersStatusBarHidden {
return NO; // your own visibility code
}
Finally, make sure your app plist does NOThave the "View controller-based status bar appearance" set to NO. Either delete that line or set it to YES (which I believe is the default now for iOS 7?)
确保最后,让您的应用程序plist中不具有“查看基于控制器的状态栏外观”设置为NO。删除该行或将其设置为 YES(我认为这是 iOS 7 现在的默认设置?)
回答by Alex Brown
For anyone still struggling with this, this simple extension in swift should fix the problem for you.
对于仍在为此苦苦挣扎的任何人,swift 中的这个简单扩展应该可以为您解决问题。
extension UINavigationController {
override open var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
回答by Luis
My app used all three: UINavigationController
, UISplitViewController
, UITabBarController
, thus these all seem to take control over the status bar and will cause preferedStatusBarStyle
to not be called for their children. To override this behavior you can create an extension like the rest of the answers have mentioned. Here is an extension for all three, in Swift 4. Wish Apple was more clear about this sort of stuff.
我的应用程序使用了所有三个:UINavigationController
, UISplitViewController
, UITabBarController
,因此这些似乎都控制了状态栏,并且不会preferedStatusBarStyle
为他们的孩子调用。要覆盖此行为,您可以创建一个扩展,就像其他答案提到的那样。这是所有三个的扩展,在 Swift 4 中。希望 Apple 对这类东西更清楚。
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
}
}
Edit: Update for Swift 4.2 API changes
编辑:更新 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
}
}
回答by Yogesh Suthar
Tyson'sanswer is correct for changing the status bar color to white in UINavigationController
.
Tyson 的答案对于将状态栏颜色更改为白色是正确的UINavigationController
。
If anyone want's to accomplish the same result by writing the code in AppDelegate
then use below code and write it inside AppDelegate's
didFinishLaunchingWithOptions
method.
如果有人想通过编写代码来完成相同的结果,AppDelegate
则使用下面的代码并将其写入AppDelegate's
didFinishLaunchingWithOptions
方法中。
And don't forget to set the UIViewControllerBasedStatusBarAppearance
to YES
in the .plist file, else the change will not reflect.
并且不要忘记在 .plist 文件中设置UIViewControllerBasedStatusBarAppearance
to YES
,否则更改不会反映。
Code
代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// status bar appearance code
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
return YES;
}
回答by frin
In addition to serenn's answer, if you are presenting a view controller with a modalPresentationStyle
(for example .overCurrentContext
), you should also call this on the newly presented view controller:
除了 serenn 的回答之外,如果您使用modalPresentationStyle
(例如.overCurrentContext
)呈现视图控制器,您还应该在新呈现的视图控制器上调用它:
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
Don't forget to also override the preferredStatusBarStyle
in the presented view controller.
不要忘记还覆盖preferredStatusBarStyle
呈现的视图控制器中的 。
回答by C?ur
On a UINavigationController, preferredStatusBarStyle
is not called because its topViewController
is preferred to self
. So, to get preferredStatusBarStyle
called on an UINavigationController, you need to change its childViewControllerForStatusBarStyle
.
在 UINavigationController 上,preferredStatusBarStyle
不会被调用,因为它topViewController
比self
. 因此,要preferredStatusBarStyle
调用 UINavigationController,您需要更改其childViewControllerForStatusBarStyle
.
Recommendation
推荐
Override your UINavigationController in your class:
在您的班级中覆盖您的 UINavigationController:
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
Non recommended alternative
不推荐的替代品
To do it for all UINavigationController, you could override in an extension (warning: it affects UIDocumentPickerViewController, UIImagePickerController, etc.), but you should probably not do it according to Swift documentation:
要为所有 UINavigationController 执行此操作,您可以在扩展中进行覆盖(警告:它会影响 UIDocumentPickerViewController、UIImagePickerController 等),但根据 Swift 文档,您可能不应该这样做:
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
open override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
回答by Artem Abramov
An addition to Hippo's answer: if you're using a UINavigationController, then it's probably better to add a category:
河马答案的补充:如果您使用的是 UINavigationController,那么最好添加一个类别:
// UINavigationController+StatusBarStyle.h:
@interface UINavigationController (StatusBarStyle)
@end
// UINavigationController+StatusBarStyle.m:
@implementation UINavigationController (StatusBarStyle)
- (UIStatusBarStyle)preferredStatusBarStyle
{
//also you may add any fancy condition-based code here
return UIStatusBarStyleLightContent;
}
@end
That solution is probably better than switching to soon-to-be deprecated behaviour.
该解决方案可能比切换到即将弃用的行为更好。
回答by abhimanyu jindal
Swift 4.2 and above
Swift 4.2 及以上
As mentioned in selected answer, root cause is to check your window root view controller object.
如所选答案中所述,根本原因是检查您的窗口根视图控制器对象。
Possible cases of your flow structure
流程结构的可能案例
- 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 findchildForStatusBarStyle
- 自定义 UIViewController 对象是窗口根视图控制器
您的窗口根视图控制器是一个 UIViewController 对象,它会根据您的应用程序流程进一步添加或删除导航控制器或 tabController。
如果您的应用程序在没有选项卡的导航堆栈上具有登录前流程和带选项卡的登录后流程,并且可能每个选项卡进一步包含导航控制器,则通常使用这种流程。 - TabBarController 对象是窗口根视图控制器
这是窗口根视图控制器是 tabBarController 的流程,可能每个选项卡都进一步包含导航控制器。 - NavigationController 对象是窗口根视图控制器
这是窗口根视图控制器是 navigationController 的流程。
我不确定是否有可能在现有导航控制器中添加标签栏控制器或新导航控制器。但是如果有这种情况,我们需要将状态栏样式控件传递给下一个容器。所以,我在 UINavigationController 扩展中添加了相同的检查来查找childForStatusBarStyle
Use following extensions, it handles all above scenarios-
使用以下扩展,它处理上述所有场景-
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 { ##代码##.childForStatusBarStyle != nil }?.childForStatusBarStyle?.preferredStatusBarStyle ?? .default
}
}
- You don't need
UIViewControllerBasedStatusBarAppearance
key ininfo.plist
as it true by default
- 您不需要
UIViewControllerBasedStatusBarAppearance
键入,info.plist
因为默认情况下为 true
Points to consider for more complex flows
对于更复杂的流程要考虑的要点
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 toNewFlowUIViewController
, then add extension ofNewFlowUIViewController
as well to manage further view controller's status bar style.In case you set modalPresentationStyleother than
fullScreen
while presenting modally, you must setmodalPresentationCapturesStatusBarAppearance
to true so that presented view controller must receive status bar appearance control.
如果您以模态方式呈现新流程,它将与现有状态栏样式流程分离。因此,假设您正在展示一个
NewFlowUIViewController
,然后将新的导航或 tabBar 控制器NewFlowUIViewController
添加到,然后添加扩展名NewFlowUIViewController
以进一步管理视图控制器的状态栏样式。如果您设置modalPresentationStyle而不是
fullScreen
在模态呈现时,您必须设置modalPresentationCapturesStatusBarAppearance
为 true 以便呈现的视图控制器必须接收状态栏外观控制。