关于iOS状态栏处理的相关方法变更:
1、iOS9以前是statusBarStyle相关样式都是由UIApplication全局统一配置,iOS9之后这些方法便遗弃了(使用的话需要plist设置View controller-based status bar appearance为NO)。
- (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated;
- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated;
- (void)setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation;
@property(readwrite, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden;
2、iOS7将其添加为UIViewController的属性(需要plist设置View controller-based status bar appearance为YES):
@property(nonatomic, readonly, nullable) UIViewController *childViewControllerForStatusBarStyle;
@property(nonatomic, readonly, nullable) UIViewController *childViewControllerForStatusBarHidden;
@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle;
@property(nonatomic, readonly) BOOL prefersStatusBarHidden;
@property(nonatomic, readonly) UIStatusBarAnimation preferredStatusBarUpdateAnimation;
- (void)setNeedsStatusBarAppearanceUpdate;
新方法说明:
新的api提供了自父控制器到子控制器的逐层控制,即由谁来控制状态栏是上层控制器用childViewControllerForStatusBarHidden和childViewControllerForStatusBarStyle方法来决定的。如果这两个方法在控制器中都返回nil,则由自己控制。
1.childViewControllerForStatusBarStyle和childViewControllerForStatusBarHidden,在UITabBarController、UINavigationController、UIViewController中实现,返回一个子控制器来控制状态栏的hidden和样式。
UINavigationController:
childViewControllerForStatusBarHidden默认返回值是topViewController
childViewControllerForStatusBarStyle默认返回值是nil
当childViewControllerForStatusBarStyle返回nil,如果父控制器指定了childViewControllerForStatusBarStyle为UINavigationController,则preferredStatusBarStyle会被调用
UITabBarController:
childViewControllerForStatusBarStyle和childViewControllerForStatusBarHidden默认都是selectedViewController,所以在UITabBarController里面实现prefersStatusBarHidden和preferredStatusBarStyle默认是不会调用的。
以前A控制器push到B控制器,B控制器pop到A,而且A、B两个控制器需要的状态栏样式不同。那么就需要在A、B中调用:
A:[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]
B:[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]
那么现在我们只需要在controller中实现如下方法,该方法就会每次在viewWillAppear之前调用:
- (UIStatusBarStyle)preferredStatusBarStyle {
if (@available(iOS 13.0, *)) {
return UIStatusBarStyleLightContent;
} else {
return UIStatusBarStyleDefault;
}}
各方法调用顺序:
1.当做视图切换操作时,首先会自上而下调用:
- UITabBarController - childViewControllerForStatusBarHidden
- UINavigationController - childViewControllerForStatusBarHidden
- currentUIViewController(即将disappear) - prefersStatusBarHidden
- UITabBarController -childViewControllerForStatusBarHidden
- UINavigationController - childViewControllerForStatusBarHidden
- nextUIViewController (即将appear) - prefersStatusBarHidden
- nextUIViewController (即将appear) - preferredStatusBarUpdateAnimation(statusBarHidden有变化会执行)
2.这时如果nextUIViewController的prefersStatusBarHidden返回YES,则直接隐藏。如果为NO,继续自上而下调用:
- UITabBarController -childViewControllerForStatusBarStyle
- UINavigationController - childViewControllerForStatusBarStyle
- UIViewController (即将appear) -preferredStatusBarStyle
对于modal出来的控制器,如果modalPresentationStyle是fullScreen,那么就可以由modal出来的控制器处理。如果不是fullScreen就可以实现modalPresentationCapturesStatusBarAppearance返回YES来处理,否则就会交给下面的ViewController来处理。
除此之外新版的statusBar显隐的动画将不能直接设置,虽然有preferredStatusBarUpdateAnimation这个方法可以返回动画样式,但并没有动画效果。需要我们在改变hidden的时候由控制器手动添加动画并调用setNeedsStatusBarAppearanceUpdate刷新:
[UIView animateWithDuration:0.5 animations:^{
[self setNeedsStatusBarAppearanceUpdate];
}];
如果需要在控制器内(而不是切换控制器)主动改变状态栏,就需要在改变后(一般设立flag,通过修改flag,控制prefer方法的返回值)调用setNeedsStatusBarAppearanceUpdate来刷新样式,系统会再次自上而下调用以上相关方法。