Ios preferredStatusBarStyle不是';我没打电话
我随后重写了Ios preferredStatusBarStyle不是';我没打电话,ios,ios7,uikit,uistatusbar,Ios,Ios7,Uikit,Uistatusbar,我随后重写了-preferredStatusBarStyle,但没有调用它。 是否有任何选项可以更改以启用它?(我在项目中使用XIB。)可能的根本原因 我也遇到了同样的问题,并且发现这是因为我没有在应用程序窗口中设置根视图控制器 我在其中实现了preferredStatusBarStyle的UIViewController用于UIAbbarController中,该控制器控制屏幕上视图的外观 当我将根视图控制器设置为指向此UITabBarController时,状态栏更改开始正常工作,正如预期的
-preferredStatusBarStyle
,但没有调用它。
是否有任何选项可以更改以启用它?(我在项目中使用XIB。)可能的根本原因
我也遇到了同样的问题,并且发现这是因为我没有在应用程序窗口中设置根视图控制器
我在其中实现了preferredStatusBarStyle
的UIViewController
用于UIAbbarController
中,该控制器控制屏幕上视图的外观
当我将根视图控制器设置为指向此UITabBarController
时,状态栏更改开始正常工作,正如预期的那样(并且调用了preferredStatusBarStyle
方法)
替代方法(在iOS 9中已弃用)
或者,您可以在每个视图控制器中根据其背景颜色调用以下方法之一(视情况而定),而不必使用setneedssStatusBarAppearanceUpdate
:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
或
请注意,如果使用此方法,您还需要将plist文件中的
UIViewControllerBasedStatusBarAppearance
设置为NO
。Hippo回答的补充:如果您使用的是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
该解决方案可能比切换到即将被弃用的行为要好。对于任何使用UINavigationController的人:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
UINavigationController
在调用其子视图控制器时不会转发preferredStatusBarStyle
。相反,它管理自己的状态——正如它应该做的那样,它在屏幕顶部绘制状态栏所在的位置,因此应该对其负责。因此,在导航控制器内的VCs中实现preferredStatusBarStyle
将不会起任何作用-它们永远不会被调用
诀窍在于UINavigationController
使用什么来决定为UIStatusBarStyleDefault
或UIStatusBarStyleLightContent
返回什么。它基于其UINavigationBar.barStyle
。默认设置(UIBarStyleDefault
)会导致出现黑暗的前景UIStatusBarStyleDefault
状态栏。而UIBarStyleBlack
将给出一个UIStatusBarStyleLightContent
状态栏
TL;医生:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
如果要在UINavigationController
上使用UIStatusBarStyleLightContent
,请使用:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
因此,我实际上向UINavigationController添加了一个类别,但使用了以下方法:
-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;
并让它们返回当前可见的UIViewController。使当前可见视图控制器可以设置其自己的首选样式/可见性
下面是完整的代码片段:
在Swift中:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
在Objective-C中:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
下面是如何在UIViewController中实现的:
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
在Swift中
override public func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
override func prefersStatusBarHidden() -> Bool {
return false
}
在Objective-C中
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // your own style
}
- (BOOL)prefersStatusBarHidden {
return NO; // your own visibility code
}
最后,确保您的应用程序plist没有将“基于视图控制器的状态栏外观”设置为否。请删除该行或将其设置为是(我认为这是iOS 7的默认设置?以下是我解决此问题的方法 定义名为AGViewControllerAppearance的协议 AGViewControllerAppearance.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
#导入
@协议AGViewControllerAppearance
@可选的
-(BOOL)showsStatusBar;
-(BOOL)animatessStatusBarVisibility;
-(UIStatusBarStyle)首选状态BarStyle;
-(UIStatusBarAnimation)首选状态Baranimation;
@结束
在UIViewController上定义一个名为升级的类别
UIViewController+Upgrade.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
#导入
@界面UIViewController(升级)
//
//替代品
//
-(void)upgradedViewWillAppear:(BOOL)动画;
@结束
UIViewController+Upgrade.m
#import "UIViewController+Upgrade.h"
#import <objc/runtime.h>
#import "AGViewControllerAppearance.h" // This is the appearance protocol
@implementation UIViewController (Upgrade)
+ (void)load
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wselector"
Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
#pragma clang diagnostic pop
Method upgradedViewWillAppear = class_getInstanceMethod(self, @selector(upgradedViewWillAppear:));
method_exchangeImplementations(viewWillAppear, upgradedViewWillAppear);
}
#pragma mark - Implementation
- (void)upgradedViewWillAppear:(BOOL)animated
{
//
// Call the original message (it may be a little confusing that we're
// calling the 'same' method, but we're actually calling the original one :) )
//
[self upgradedViewWillAppear:animated];
//
// Implementation
//
if ([self conformsToProtocol:@protocol(AGViewControllerAppearance)])
{
UIViewController <AGViewControllerAppearance> *viewControllerConformingToAppearance =
(UIViewController <AGViewControllerAppearance> *)self;
//
// Status bar
//
if ([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)])
{
BOOL shouldAnimate = YES;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(animatesStatusBarVisibility)])
{
shouldAnimate = [viewControllerConformingToAppearance animatesStatusBarVisibility];
}
[[UIApplication sharedApplication] setStatusBarStyle:[viewControllerConformingToAppearance preferredStatusBarStyle]
animated:shouldAnimate];
}
if ([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)])
{
UIStatusBarAnimation animation = UIStatusBarAnimationSlide;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(prefferedStatusBarAnimation)])
{
animation = [viewControllerConformingToAppearance prefferedStatusBarAnimation];
}
[[UIApplication sharedApplication] setStatusBarHidden:(! [viewControllerConformingToAppearance showsStatusBar])
withAnimation:animation];
}
}
}
@end
#导入“UIViewController+Upgrade.h”
#进口
#导入“AGViewControllerAppearance.h”//这是外观协议
@实现UIViewController(升级)
+(空)荷载
{
#pragma-clang诊断推送
#pragma-clang诊断被忽略“-Wselector”
方法viewWillAspect=class_getInstanceMethod(self,@selector(viewWillAspect:);
#pragma-clang诊断流行语
方法upgradedViewWillAppear=class_getInstanceMethod(self,@selector(upgradedViewWillAppear:);
方法交换实施(视图将显示,升级视图将显示);
}
#pragma标记-实现
-(void)upgradedViewWillAppear:(BOOL)动画
{
//
//调用原始消息(可能有点困惑,我们正在
//调用“相同”方法,但实际上我们调用的是原始方法:))
//
[自升级视频:动画];
//
//实施
//
if([自确认协议:@协议(AGViewControllerAppearance)])
{
UIViewController*ViewControllerConforming to Appearance=
(UIViewController*)自身;
//
//状态栏
//
if([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)])
{
BOOL shouldAnimate=是;
if([viewControllerConformingToAppearance respondsToSelector:@selector(AnimateStatusBarVisibility)])
{
shouldAnimate=[ViewControllerConforming to Appearance AnimagesStatusBarVisibility];
}
[[UIApplication sharedApplication]setStatusBarStyle:[ViewControllerConforming to Appearance preferredStatusBarStyle]
动画:应设置动画];
}
if([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)])
{
UIStatusBarAnimation动画=UIStatusBarAnimation幻灯片;
如果([viewControllerConformingT
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
open override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override open var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
override open var childViewControllerForStatusBarHidden: UIViewController? {
return topViewController
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barStyle = UIBarStyle.black
}
}
extension UINavigationController {
override open var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
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
}
}
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
}
}
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
override var childViewControllerForStatusBarStyle: UIViewController? {
var childViewController = visibleViewController
if let controller = childViewController, controller.isBeingDismissed {
childViewController = topViewController
}
return childViewController?.childViewControllerForStatusBarStyle ?? childViewController
}
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
}
}
@interface UINavigationController (StatusBarStyle)
+ (void)setUseLightStatusBarStyle;
@end
#import "UINavigationController+StatusBarStyle.h"
#import <objc/runtime.h>
@implementation UINavigationController (StatusBarStyle)
void (^swizzle)(Class, SEL, SEL) = ^(Class c, SEL orig, SEL new){
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
};
+ (void)setUseLightStatusBarStyle {
swizzle(self.class, @selector(preferredStatusBarStyle), @selector(_light_preferredStatusBarStyle));
}
- (UIStatusBarStyle)_light_preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
@end
#import "UINavigationController+StatusBarStyle.h"
[UINavigationController setUseLightStatusBarStyle];