在iOS應(yīng)用程序開發(fā)中,狀態(tài)欄是顯示在屏幕頂部的系統(tǒng)信息條,用于顯示信號(hào)、電量等重要信息。有時(shí)候我們需要對(duì)狀態(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è)鏈條得通。所以要對(duì) 容器做處理,實(shí)現(xiàn)狀態(tài)欄相關(guān)的詢問方法。
比如,對(duì)于Tabbar控制器,我們這么寫
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.selectedViewController;
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.selectedViewController;
}
對(duì)于導(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è)置。