一、前言
之前在《iOS MVVM+RAC 从框架到实战》中介绍了一下MVVM下的框架基类,其中的ViewController的基类中有对UIStatusBar的操作:更改statusBar的显示风格和隐藏,然后有童鞋提出不管事...ԅ( ¯་། ¯ԅ)
it's my fault! 上传Demo之前并没有认真检查各个函数...,就只整理了与之前文章相关的基类方法,还好有这么细心的童鞋提出来,本来想@一下这位童鞋,可刚发现评论里没有这个了,怀疑是不是因为我没有及时回复就生气了...就把评论删除了>_<|||,真真是刚腾出时间来处理,见谅啊!希望你能收到我的道歉啊o(╯□╰)o。
二、失效原因
1、对于隐藏显示StatusBar
因为做之前的项目的时候,将其返回值写死了,所以在子类重新调用设置的时候返回值并没有变,都是不隐藏的。然后之前想要干掉基类的时候将其系统函数的前缀也改了,所以也不会被调用,额,大致意思就是这样。
2、对于更改StatusBar风格
之前只是测试框架的时候用过,并没有使用UINavigationController作为Root,所以没有测试出来,假如是这种情况下我们自己的UIViewController的preferredStatusBarStyle
函数不会被调用。
三、更改后的代码
YDViewController.m 内相关代码
@interface YDViewController ()
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;
@property (nonatomic, assign) BOOL statusBarHidden;
@property (nonatomic, assign) BOOL changeStatusBarAnimated;
@end
#pragma mark - system
- (UIStatusBarStyle)preferredStatusBarStyle {
if (self.statusBarStyle) {
return self.statusBarStyle;
} else {
return UIStatusBarStyleLightContent;
}
}
- (BOOL)prefersStatusBarHidden {
return self.statusBarHidden;
}
- (void)changeStatusBarStyle:(UIStatusBarStyle)statusBarStyle
statusBarHidden:(BOOL)statusBarHidden
changeStatusBarAnimated:(BOOL)animated {
self.statusBarStyle=statusBarStyle;
self.statusBarHidden=statusBarHidden;
if (animated) {
[UIView animateWithDuration:0.25 animations:^{
[self setNeedsStatusBarAppearanceUpdate];
}];
}
else{
[self setNeedsStatusBarAppearanceUpdate];
}
}
YDNavigationController.m 内相关代码
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.topViewController;
}
四、 方法解析
- (UIStatusBarStyle)preferredStatusBarStyle:
此系统函数返回的是系统定义的几种状态栏前景风格,若返回的是固定的值,那当此VC显示的时候会调用此方法,改变当前的VC的StatusBar风格。
假如VC已经显示的情况下想要刷新风格,可使用
setNeedsStatusBarAppearanceUpdate
方法。
- (void)setNeedsStatusBarAppearanceUpdate
这个方法会通知系统去调用当前UIViewController的 preferredStatusBarStyle
方法,更准确点说是让系统去调用application.window的rootViewController的 preferredStatusBarStyle方法
,如果rootViewController的childViewControllerForStatusBarStyle
返回值不为nil,则再具体讨论。
- (UIViewController *)childViewControllerForStatusBarStyle:
此方法就是在Demo内新加的方法,不重写的话默认返回nil。
如第三部分的代码,我使用的是 setNeedsStatusBarAppearanceUpdate
,来刷新的当前的VC的StatusBar状态,当我们调用这个方法的时候,系统会调用application.window的rootViewController的 preferredStatusBarStyle
方法, 但是Demo是用的UINavigationController做root,这种情况下我们自己的UIViewController里的 preferredStatusBarStyle
根本不会被调用.
解决方法就是在自定义的Nav里添加如下代码:
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.topViewController;
}
上面的代码很简单,就是告诉系统不要调用我自己(就是UINavigationController)的 preferredStatusBarStyle
方法,而是去调用navigationController.topViewController的 preferredStatusBarStyle
方法,这样就又能成功调用到我们写的 - (UIStatusBarStyle)preferredStatusBarStyle:
方法了。
对此总结来说就是:只要UIViewController重写的的 childViewControllerForStatusBarStyle
方法返回值不是nil,那么,UIViewController的 preferredStatusBarStyle
方法就不会被系统调用,系统会调用 childViewControllerForStatusBarStyle
方法返回的UIViewController的 preferredStatusBarStyle
方法。
五、statusBar背景的设置(额外记录一下)
1、系统方法:
- navigationBar的
setBarTintColor
方法:更改statusBar的背景色 - navigationBar的
- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics
: 更改statusBar的背景图片,注意此时setBarTintColor
就不起作用了,背景色就是纯黑色了。
2、自定义方法
- 直接写一个view贴到navigationBar上,具体代码就不写了,之前因为要做Nav的动画隐藏和显示,需要更换背景,就是用的这个方法...o(╯□╰)o,也还行没出啥大问题。