先说下iOS9之前的方法
——————iOS9之前——————
全局隐藏状态栏和设置样式
1、在工程的info.plist文件中, 添加View controller-based status bar appearance
-->值为: NO
2、在AppDelegate中加上[[UIApplication sharedApplication] setStatusBarHidden:YES];
3.设置状态栏样式[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent/UIStatusBarStyleDefault];
@interface UIApplication(UIApplicationDeprecated)
// Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
@property(readwrite, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden
NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController prefersStatusBarHidden]") __TVOS_PROHIBITED;
- (void)setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation
NS_DEPRECATED_IOS(3_2, 9_0, "Use -[UIViewController prefersStatusBarHidden]") __TVOS_PROHIBITED;
// Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
这句注释表明,如果使用视图控制器去设置状态栏,UIApplication里的statusBarHidden方法不生效,setStatusBarStyle同理。所以要View controller-based status bar appearance
-->值为:NO
某些页面隐藏状态栏和设置样式
由于[UIApplication sharedApplication]是全局性的,只要设置过一次隐藏,所有页面都是会隐藏状态栏。如果你想要在某些页面单独设置隐藏状态栏,先在AppDelegate中设置显示状态栏[[UIApplication sharedApplication] setStatusBarHidden:NO];
然后在某一个ViewController的viewWillAppear里设置隐藏,再在viewWillDisappear里还原之前的设置。
状态栏样式同理。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
——————iOS9之后————————
iOS9之后上述的方法苹果已经不推荐使用了,这些方法能用但是会报警告。注释提示苹果推荐使用Use -[UIViewController prefersStatusBarHidden]
这是iOS7之后苹果在UIViewController里添加的新方法,这么做的目的可以让开发者更加灵活的自定义每个ViewController的状态栏。
如果要使用prefersStatusBarHidden
方法,那么必须将View controller-based status bar appearance
-->值为: YES
,并且setStatusBarHidden和setStatusBarStyle方法会失效
取而代之的是:
- (BOOL)preferredStatusBarHidden{
return YES;
}
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
只要在UIViewController里重写了这两个方法,那么在ViewController显示的时候状态栏就会变成上面设置的样式
全局隐藏状态栏和设置样式
改用[UIViewController prefersStatusBarHidden]方法设置状态栏之后,APP运行后,应用不再读取UIApplication 的statusBarHidden和statusBarStyle这两个属性去设置状态栏,而是根据AppDelegate.window.rootViewController
里的方法,这时首先会调用的是rootViewController中的childViewControllerForStatusBarHidden
函数,因为默认返回nil,那么接下来就会调用rootViewController本身的prefersStatusBarHidden
方法和preferredStatusBarStyle
方法。因此想要全局设置状态栏,只要在根视图rootViewController里重写这俩个方法即可。
但是通常来说AppDelegate.window.rootViewController
都是UINavigationController,应用只会调用UINavigationController的方法,返回都是默认值,所以已经在自己的ViewController里写了- preferredStatusBarHidden, 却一点都不起作用。
当AppDelegate.window.rootViewController
是UINavigationController,想要全局设置状态栏和样式,可以在UINavigationController里重写prefersStatusBarHidden
方法和preferredStatusBarStyle
方法即可
某些页面隐藏状态栏和设置样式
当AppDelegate.window.rootViewController
是UINavigationController,不能在UINavigationController里重写prefersStatusBarHidden
方法和preferredStatusBarStyle
方法,而是自己创建一个继承于UINavigationcontroller的NavigationController,在这个子类中重写childViewControllerForStatusBarHidden 和childViewControllerForStatusBarStyle函数
- (UIViewController *)childViewControllerForStatusBarHidden{
return self.topViewController;
}
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.topViewController;
}
然后在每一个新的ViewController里根据需要重写prefersStatusBarHidden
方法和preferredStatusBarStyle
方法
这样每push或者pop一个vc,状态栏都是根据最上层的vcprefersStatusBarHidden
方法和preferredStatusBarStyle
方法去设置
setNeedsStatusBarAppearanceUpdate
UIViewController里的prefersStatusBarHidden方法和preferredStatusBarStyle方法,系统调用时机早于ViewController显示时viewDidAppear,因此只能决定ViewController显示时的状态栏,如果之后状态栏发生变化,需要显示的调用setNeedsStatusBarAppearanceUpdate
@property (nonatomic, assign) BOOL statusBarHidden;
- (BOOL)preferredStatusBarHidden{
return self.statusBarHidden;
}
- (void)needChangeStatusBarHidden {
self.statusBarHidden = YES;
[self setNeedsStatusBarAppearanceUpdate]; //立即更新状态栏
}