记 iOS Status Bar 状态栏 的一次革命

时隔多多多多多日,突然又又又又又又想写点东西了!写这篇文章呢,主要有两个想法:对于初学的小弟弟们,讲清楚一个知识点的历史走向,梳理顺向的开发流程,做到在项目经理的催活洪流中有条不紊。对于有些经验可做谈资的大哥哥们,可以借鉴苹果系统的设计模式和工作理念,从中吸取完美框架的设计思路。我仅代表伍丽娟祝大家七夕节快乐。

状态栏的发展洪流

咳咳,瓜子准备好了么?如果没有准备好,请到我的微博第一条置顶微博处免费领取,下面请用心的欣赏我的表演。

2007年,iOS随iPhone亮相,开发者们觉得呢,我的电池栏总是白底黑字,不能适应我司产品诡异且有丰满的样式追求呀。响应大家号召,随即iOS2于2008年7月11日上市,带来了关于状态栏的一系列操作的API,随即iOS3.2对这套API的进行了优化,大家可以从下面的代码中稍微的领悟一下。

@interface UIApplication()

@property(nonatomic,getter=isProximitySensingEnabled) BOOL proximitySensingEnabled NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED; // default is NO. see UIDevice for replacement
- (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED; // use -setStatusBarHidden:withAnimation:

// Explicit setting of the status bar orientation is more limited in iOS 6.0 and later.
@property(readwrite, nonatomic) UIInterfaceOrientation statusBarOrientation NS_DEPRECATED_IOS(2_0, 9_0, "Explicit setting of the status bar orientation is more limited in iOS 6.0 and later") __TVOS_PROHIBITED;
- (void)setStatusBarOrientation:(UIInterfaceOrientation)interfaceOrientation animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 9_0, "Explicit setting of the status bar orientation is more limited in iOS 6.0 and later") __TVOS_PROHIBITED;

// Setting the statusBarStyle does nothing if your application is using the default UIViewController-based status bar system.
@property(readwrite, nonatomic) UIStatusBarStyle statusBarStyle NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]") __TVOS_PROHIBITED;
- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]") __TVOS_PROHIBITED;

// 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;

@end

大概的意思呢,就是顺着大家的合理思维,苹果工程师认为状态栏是统一共用的,所以控制是统一的,由UIApplication来确定,感觉自己的设计简直完美。就这样过了5年,你的青春期消耗殆尽,伴随着开发者对于这套API的疯狂吐槽,苹果工程师们推出了一套由UIViewController来确定状态栏各种状态的API,由中央集权制一下子改成了封建制。同时呢,为了让大家有一个过度的周期,直到2015年,iOS9的时候,才宣布UIApplication的这套API废除。我们来看一下这套新的依附于UIViewController的API。

@interface UIViewController : UIResponder
// Override to return a child view controller or nil. If non-nil, that view controller's status bar appearance attributes will be used. If nil, self is used. Whenever the return values from these methods change, -setNeedsStatusBarAppearanceUpdate should be called.
@property(nonatomic, readonly, nullable) UIViewController *childViewControllerForStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
@property(nonatomic, readonly, nullable) UIViewController *childViewControllerForStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;

@property(nonatomic,assign) BOOL modalPresentationCapturesStatusBarAppearance NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;

@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
@property(nonatomic, readonly) BOOL prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
// Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.
@property(nonatomic, readonly) UIStatusBarAnimation preferredStatusBarUpdateAnimation NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarAnimationFade

// This should be called whenever the return values for the view controller's status bar attributes have changed. If it is called from within an animation block, the changes will be animated along with the rest of the animation block.
- (void)setNeedsStatusBarAppearanceUpdate NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;

@end

那么相信大家感觉到不妙,仿佛看到了自己队友写的代码,管它现有业务怎么实现的,自己同时再搞一套,无限Happy。但是,苹果工程师还是比较有职业操守的,我们只需要在Info.plist中设置View controller-based status bar appearance字段,为YES呢,则由UIViewController方法自行决定,为NO呢,则使用UIApplication全局方法决定。毫无疑问,默认值为YES

也就是这样,很多新手走上迷茫而又不知所措的道路,感觉状态栏哇塞,好神奇,该隐藏的时候不隐藏,该出现不出现,很多老项目两种控制方式的代码共存,导致新手小弟弟无心工作,心中MMP。下面,出于代码王的社会责任感,我将给各位小弟弟们耐心的讲解一下如何干死那些你看着不顺眼的老油条们,嗯...,不对,是如何完成一个APP状态栏的控制体系。

从0开始完整搭建状态栏体系

确定控制方式(中央集权制 & 封建制)

在我们新建项目之前,我们要做一个重大而坚决的决定,决定你的状态栏的控制方式。上面也有提到,在Info.plist中设置View controller-based status bar appearance字段,为YES呢,则由UIViewController方法自行决定,为了后文方便阐述,我们叫它封建制。为NO呢,则使用UIApplication全局方法决定,同样的,我们叫它中央集权制。系统默认是封建制

目前很多老项目都存在两种控制方式代码并存的情况,请务必永远不要在项目中珍藏自己的无用或者有可优化控件的代码!那么问题来了,你写的代码属于什么垃圾呢?

API规则分析

无论使用哪种控制方式,无非就是控制显隐样式动画三个方面,API也都很简单,不做过多赘述。

开局走好第一步

我们创建一个新项目,发现应用启动的欢迎页面电池栏默认是存在的,略显一丝突兀与不和谐,为了让用户有一个良好全面和谐的关注点,那么我们如何隐藏欢迎页面的状态栏呢?这位同学问得好!这个处理方式也很简单,只需要在Info.plist中添加Status bar is initially hidden,并设置为YES,就能够实现一个非常高级的技术点,那就是启动欢迎页面隐藏电池栏。

如果你们应用是一个有个性的应用,你也是一个非常有个性的开发,于是,你们决定欢迎页面要显示电池栏,这样会显得更加的开放与潮流,并且要定制状态栏的样式为UIStatusBarStyleLightContent,那么你需要在Info.plist中添加Status bar style,并设置为UIStatusBarStyleLightContent,恭喜你,你已经完成了和产品的灵魂契合。在这里需要注意一点,如果你选择中央集权制,那么这个字段代表了整个项目的默认状态栏样式,如果为封建制,它仅仅代表欢迎页面的状态栏样式。

中央集权制轮转控制法

首先,表明观点,无论你们项目现在的控制方式,我不建议再继续使用这种方式进行迭代。苹果虽然表示这套API在iOS9之后废弃,但是并不影响使用,这也是很多项目迟迟不作出调整的原因。这种方式对于多页面不同状态的控制有一些不太友好,需要记录每个页面的状态栏特性,并适时的时候利用全局方法进行调整,尤其在一个项目生态中对于新手接受程度是一个考验。

封建制各国各制控制法

苹果在iOS7之后推出了这种控制方式,每个页面自行控制状态栏的各种状态,系统会自动根据每个UIViewController的对应方法的返回值进行状态栏的调整,无需做多余的控制。例如:

@implementation YSViewController

...
...

- (BOOL)prefersStatusBarHidden {
    return NO;
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
    return [super preferredStatusBarUpdateAnimation];
}
@end

表示当这个页面展示时,显示状态栏,使用UIStatusBarStyleLightContent样式,更新状态栏时使用默认动画方式。相对来说,对新手友好度偏高,不至于在历史原因中迷失了一个初级程序员的天真与无邪。

同样的,有人会问,如果我在不同的情况下该页面的状态栏的状态是不确定的,甚至是根据用户的操作实时改变的,使用中央集权制呢,我只需要调用相关方法,直接就能调整为对应的样式,那我们使用封建制又该怎么操作呢?这位同学这个问题问得好!根据苹果一贯的设计,他想要更新一种可视化的状态,我觉得他会有类似于setNeedsLayout或者sizeToFit的设计,你觉得呢?看一下新的API,你会发现setNeedsStatusBarAppearanceUpdate,是不是如出一辙呢?那你能联想到什么呢?欢迎评论区发表你的观点和认识。

总结

今天就到这吧,关于状态栏想说的其实不止于此,我们可以从其中获取到更为深刻的东西。不得不说,苹果整个生态的设计比较稳定,但是如果有大的框架变动,我们在骂街的同时,是不是应该从中获取到一些别样的东西去辅助我们对于设计模式更为深刻的理解呢?作为一个资深的程序员,如果还在沉醉于+1式的技术积累,你革的是谁的命呢?如果还是习惯性的保留无用或者可优化的代码,无论不舍或懒惰,那你革的又是谁的命呢?


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 我们为什么没有目标,没有目标是因为我们没有内在驱动力,没有内在驱动力的原因是经济问题还没有得到解决,经济没有得到解...
    陈俊婷峰硅胶阅读 247评论 0 0
  • 敬爱的李老师,智慧的班主任,亲爱的跃友们大家好: 2019年7月6号我是(管西芹),我的日精进行动第357天和大家...
    管西芹阅读 95评论 0 0
  • 1016第二课 基金的分类 1:按基金投资对象,分为货币基金、债券基金、混合基金和股票基金。风险由低到高。 2:按...
    爱笑的水晶阅读 71评论 0 0
  • 春秋多少梦,只在一心间。 跃马何足道,平常最自然。 (五绝·自然,新韵,戊戌年十一月廿三夜。多少事不由心,多少梦太...
    君子包阅读 436评论 2 10