在iOS應(yīng)用程序開發(fā)中娩践,狀態(tài)欄是顯示在屏幕頂部的系統(tǒng)信息條活翩,用于顯示信號(hào)逞带、電量等重要信息。有時(shí)候我們需要對狀態(tài)欄顏色進(jìn)行自定義纱新,但在實(shí)際開發(fā)中可能會(huì)遇到一些困難展氓。
之前寫過iOS狀態(tài)欄如何設(shè)置的問題,見鏈接 iOS狀態(tài)欄設(shè)置 - 簡書 (jianshu.com)
我們用的方案是 控制器優(yōu)先控制狀態(tài)欄的展示脸爱,也就是默認(rèn)的遇汞,狀態(tài)欄的文字是黑色的。在需要更新狀態(tài)欄顏色的控制器返回需要的樣式簿废,比如在視頻播放器頁面狀態(tài)欄文字返回白色空入。
問題描述
但是最近遇到了狀態(tài)欄不更新的問題。問題是這樣的族檬,在使用模態(tài)方式(模態(tài)風(fēng)格是custom)彈出了帶導(dǎo)航欄的控制器后歪赢,使用該控制器,push 一個(gè)需要展示 白色文字 狀態(tài)欄的 視圖控制器单料,這個(gè)控制器關(guān)于狀態(tài)欄的方法一直未被調(diào)用埋凯,導(dǎo)致使用的還是黑色文字的狀態(tài)欄。
就是 圖中 這個(gè)導(dǎo)航 push 出來的頁面控制器 狀態(tài)欄相關(guān)的方法都沒有被調(diào)用扫尖。導(dǎo)致狀態(tài)欄沒有更新為預(yù)期的樣子白对。
問題分析
而不是這種present出來的導(dǎo)航push就沒有這個(gè)問題。更嚴(yán)格的說换怖,模態(tài)方式是 UIModalPresentationFullScreen 這種方式 也是沒有問題的甩恼。但問題使用其他的方式 比如 UIModalPresentationCustom 或者 UIModalPresentationOverFullScreen 或者 UIModalPresentationOverCurrentContext 會(huì)有這個(gè)問題。這說明模態(tài)方式沉颂,也會(huì)影響狀態(tài)欄的設(shè)置条摸。
而我們的業(yè)務(wù)需要這個(gè)present出來的頁面是半透明的,因此不能用UIModalPresentationFullScreen铸屉,只能用 UIModalPresentationCustom 或者 UIModalPresentationOverFullScreen钉蒲,使用這種方式,狀態(tài)欄就是不能正確更新抬探。
我們無法更改 UIModalPresentationStyle ,只能 想辦法 讓 我們viewController狀態(tài)欄相關(guān)的方法得到調(diào)用子巾。
問題處理
第一步: 打通狀態(tài)欄樣式的傳遞鏈條
以視圖控制器優(yōu)先控制狀態(tài)欄的方式中,window的狀態(tài)管理器會(huì)層層詢問小压,如果問到了就不再詢問,比如會(huì)問window的root VC椰于,狀態(tài)欄要展示什么怠益,root VC 如果返回了就不再繼續(xù),通常 rootVC是個(gè)容器控制器瘾婿,會(huì)詢問子控制器蜻牢,一直問到結(jié)果位置烤咧,因此,要想 子控制的狀態(tài)欄相關(guān)的方法會(huì)被調(diào)用抢呆,這個(gè)鏈條得通煮嫌。所以要對 容器做處理,實(shí)現(xiàn)狀態(tài)欄相關(guān)的詢問方法抱虐。
比如昌阿,對于Tabbar控制器,我們這么寫
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.selectedViewController;
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.selectedViewController;
}
對于導(dǎo)航控制器恳邀,我們這么寫
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
第二步: 模態(tài)時(shí)接管狀態(tài)欄的處理
通過第一步懦冰,我們保證了即便控制器被包括在容器中,也都有機(jī)會(huì)處理狀態(tài)欄谣沸。
然而刷钢,這么寫,仍然沒有解決我們的問題乳附,我們的方法沒有被調(diào)用内地,因?yàn)閳D中那個(gè)導(dǎo)航控制器相關(guān)的詢問事件都沒有觸發(fā)「吵看似是系統(tǒng)導(dǎo)致的瓤鼻,我們很難找到原因,我們只知道模特的方法影響了狀態(tài)欄響應(yīng)鏈條的傳遞贤重。
經(jīng)過仔細(xì)的分析茬祷,不停的試一試,我們終于找到了問題的關(guān)鍵并蝗。當(dāng)我們以模態(tài)方式出現(xiàn)時(shí)祭犯,并且有些模態(tài)方式,控制器是拿不到狀態(tài)欄的掌控權(quán)的滚停,其中有一個(gè)屬性就是用來做這個(gè)事情的沃粗。這個(gè)屬性就是 modalPresentationCapturesStatusBarAppearance
該屬性的默認(rèn)值是NO,也就是說 以模態(tài)方式出現(xiàn)時(shí)键畴,默認(rèn)不 捕獲狀態(tài)欄的 處理最盅。
然而,我們肯定是要接管狀態(tài)欄的處理的起惕,因?yàn)楸仨殞⑦@個(gè)屬性設(shè)置為YES涡贱,可以通過復(fù)寫 也可以直接設(shè)置。
在我們的問題中惹想,我們只需要復(fù)寫或者設(shè)置這個(gè)屬性问词,一定接管 狀態(tài)欄的處理,我們的問題就得到了解決嘀粱。
- (BOOL)modalPresentationCapturesStatusBarAppearance {
return YES;
}
通過以上兩個(gè)步驟激挪,讓我們的應(yīng)用徹底掌握狀態(tài)欄的設(shè)置辰狡。