我遵循这个线程重写-preferredStatusBarStyle,但它没有被调用。 有什么选项我可以改变来启用它吗?(我在我的项目中使用xib。)
当前回答
这是我解决这个问题的方法。
定义一个名为AGViewControllerAppearance的协议。
AGViewControllerAppearance.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
在UIViewController上定义一个名为Upgrade的类别。
UIViewController+Upgrade.h
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
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
现在,是时候说你的视图控制器正在实现AGViewControllerAppearance协议。
例子:
@interface XYSampleViewController () <AGViewControllerAppearance>
... the rest of the interface
@end
当然,你可以实现其余的方法(showsStatusBar, animatesStatusBarVisibility, prefereredstatusbaranimation)从协议和UIViewController+升级将做适当的 基于它们提供的值进行定制。
其他回答
注意,当使用self.navigationController.navigationBar.barStyle = UIBarStyleBlack;解决方案
请确保进入你的plist并设置“基于视图控制器的状态栏外观”为YES。如果不是,它将不起作用。
可能的根本原因
我也遇到了同样的问题,我发现这是因为我没有在我的应用程序窗口中设置根视图控制器。
我在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。
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
这种解决方案可能比切换到即将被弃用的行为要好。
如果你的viewController在UINavigationController下面。
子类UINavigationController并添加
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
ViewController的preferredStatusBarStyle将被调用。
从Xcode 11.4开始,覆盖UINavigationController扩展中的preferredStatusBarStyle属性不再有效,因为它将不会被调用。
将navigationBar的barStyle设置为.black确实有效,但如果你向navigationBar添加子视图,它可能在明暗模式下具有不同的外观,则会添加不必要的副作用。因为通过将barStyle设置为黑色,嵌入在navigationBar中的视图的userInterfaceStyle将始终具有userInterfaceStyle。不管应用程序的userinterfacstyle是暗的。
我提出的正确解决方案是通过添加UINavigationController的子类并覆盖preferredStatusBarStyle。如果你使用这个自定义的UINavigationController为你所有的视图,你将在保存侧。
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- Ios模拟器:如何关闭应用程序
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- Swift:声明一个空字典
- 在成功提交我的应用程序后,“太多符号文件”
- 首先添加一个UIView,甚至是导航栏
- 我如何改变UIButton标题颜色?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- CFNetwork SSLHandshake iOS 9失败
- 请求失败:不可接受的内容类型:文本/html使用AFNetworking 2.0
- 缺少推荐的图标文件-该包不包含iPhone / iPod Touch的应用程序图标,像素为“120x120”,png格式
- 以编程方式创建segue