說了很多難懂的東西,究竟如何自定義任意一個VC的狀態欄前景顏色呢?
我機智的把結果放到最前面,后面自己的摸索過程,想看的可以看看,估計你們也沒有興趣哈哈.
想要任意修改一個vc(非navigationController得子控制器)的狀態欄 需要
1-info.plist中 UIViewControllerBasedStatusBarAppearance 要設置YES
2-vc和上面的vc們的setNeedsStatusBarAppearanceUpdate方法不super
或者干脆不重寫setNeedsStatusBarAppearanceUpdate方法 (大家一般是不會重寫的,哈哈,所以這條基本可以忽略了)
3-然后還需要修改prefer方法中的UIStatusBarStyle(就是立即刷新之前要修改內容才可以)
4-然后調用setNeedsStatusBarAppearanceUpdate方法(條件都滿足了 最后就update)
想要任意修改一個vc(navigationController得子控制器)的狀態欄 需要
1.navVC重寫childViewControllerForStatusBarStyle方法如下返回棧頂控制器
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
2.在子控制器重寫prefer方法,返回設定的style
有沒有不區分是否是navigationController的通用設定vc的狀態欄前景的方法呢?
采用iOS9過期的方法
- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]") __TVOS_PROHIBITED;(要用新的代替參考上面區分是否被navigationController持有)
1.info.plist中 UIViewControllerBasedStatusBarAppearance 要設置NO
2.viewWillAppear方法中調用[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
3.viewWillDisappear方法中調用[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
appdelegate.m navigationController.m 和scanCodeController.m 都重寫了preferredStatusBarStyle方法View controller-based status bar appearance 設為YES只會走[JWKNavigationController preferredStatusBarStyle]View controller-based status bar appearance 設為NO哪個也不走(其實appdelegate 重寫沒鳥用,根本就是控制器的方法!)
在info.plist中增加了Status bar style,那么啟動就是這個樣式,而且target中的數據也會隨之改變.
View controller-based status bar appearance 默認是 NO 就是說在vc中重寫preferredStatusBarStyle不生效.View controller-based status bar appearance YES,vc重寫preferredStatusBarStyle 才會生效;[self setNeedsStatusBarAppearanceUpdate]可以立即調用preferredStatusBarStyle
當我們調用setNeedsStatusBarAppearanceUpdate時,系統會調用self(誰調用的這個方法,就執行誰的)的preferredStatusBarStyle方法.- (UIViewController *)childViewControllerForStatusBarStyle:這個接口也很重要,默認返回值為nil
如果在vc中重寫了setNeedsStatusBarAppearanceUpdate,里面什么也沒干的話,vc modal出下一個控制器三個方法都不會調用,而且肯定的是vc即將disAppear的時候會自動調用setNeedsStatusBarAppearanceUpdate一次.但是rootVC顯示時候,三個方法都會調用,先調用setNeedsStatusBarAppearanceUpdate,然后childViewControllerForStatusBarStyle,最后preferredStatusBarStyle
- (void)setNeedsStatusBarAppearanceUpdate {// [super setNeedsStatusBarAppearanceUpdate];}
特殊如果modal的是navigationController 會先調用navigationController的setNeedsStatusBarAppearanceUpdate方法一次,然后再調用該控制器的setNeedsStatusBarAppearanceUpdate方法一次.navigationController的跟控制器的三個方法還是不調用.如果navigationController的rootVC dismiss的話,不調用navigationController和rootVC的三個方法反而會調用modal出navigationController的控制器的setNeedsStatusBarAppearanceUpdate方法.然后rootVC和navigationController都會dealloc當控制器即將銷毀
的時候 是不會調用控制器的三個方法的.如果只有一個rootVC的navVC modal出另一個控制器(navVC還是一個子控制器),只會調用navVC的setNeedsStatusBarAppearanceUpdate方法1次,這個新的modal出來的控制器 dismiss的時候,也是只會調用navVC的setNeedsStatusBarAppearanceUpdate方法1次.如果a控制器 modal出來navVC NACVC下面的子控制器中 任意一個子控制器 dismiss,就會直接跳轉到a控制器,navVC 和 它的子控制器都會銷毀.如果navVc的a控制器 push b控制器時候,只會調用navVC的setNeedsStatusBarAppearanceUpdate方法1次, 同樣點擊pop b控制器,只會調用navVC的setNeedsStatusBarAppearanceUpdate方法1次.如果項目的根控制器重寫方法 調用super的方法- (void)setNeedsStatusBarAppearanceUpdate { NSLog(@"%s",func); [super setNeedsStatusBarAppearanceUpdate];}modal的first控制器沒有調用super方法結果是
會調用first的childViewControllerForStatusBarStyle和preferredStatusBarStyle,而不會調用setNeedsStatusBarAppearanceUpdate,當first要modal出second控制器時候才會調用setNeedsStatusBarAppearanceUpdate.也就是只要控制器被掩蓋壓棧,都會調用setNeedsStatusBarAppearanceUpdate 1次,和之前的情況是一樣的.只要調用childViewControllerForStatusBarStyle,就會調用preferredStatusBarStyle方法.
然后first modal second 結果如下
由于first沒有 super,所以只會調用first 的 setNeedsStatusBarAppearanceUpdate,不會向上追溯setNeedsStatusBarAppearanceUpdate,也不會往下調用second的兩個個方法.setNeedsStatusBarAppearanceUpdate 是否super 決定了 1.是否向上追溯前面的控制器這個方法 2.是否向下調用棧頂控制器2個方法
如果 rootVC和firstVC 都調用了super,結果如下
a modal b的時候,會先調用a的setNeedsStatusBarAppearanceUpdate,然后再調用rootVC的setNeedsStatusBarAppearanceUpdate方法.setNeedsStatusBarAppearanceUpdate 具有向上追溯性
當從 b dismiss 到 a 結果如下
不僅僅會 調用 a 和 rootVC的setNeedsStatusBarAppearanceUpdate,還會調用a的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.再繼續從a dismiss 到 rootVC 結果如下不僅僅會 調用rootVC的setNeedsStatusBarAppearanceUpdate,還會調用rootVC的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.
只要vc 調用了 super 那么 vc dismiss的時候就會調用 上一級vc 直到rootVC的setNeedsStatusBarAppearanceUpdate方法,然后再調用上一級vc的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.實現調用super setNeedsStatusBarAppearanceUpdate dismiss會調用 上層vc們的setNeedsStatusBarAppearanceUpdate 和 上一級vc的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.
但是如果上級沒有super,就不會調用上一級的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法
rootVC 和 first super了,second沒有super,一路modal過來 結果如下
會調用三個控制器的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法再往下modal navigationController帶著third 兩個都super,也就是只有second沒有super,結果如下
沒有調用navigationController和third的childViewControllerForStatusBarStyle或者preferredStatusBarStyle方法說明前面的控制器都super了,向下modal 就會調用下一級vc的 childViewControllerForStatusBarStyle和preferredStatusBarStyle方法,如果前面一級沒有super,那么后面一級就不會調用這個兩個方法了.反過來向前dismiss時候, 本級和之前的vc都super了,下一級dismiss到本級才會調用本級的childViewControllerForStatusBarStyle和preferredStatusBarStyle方法
也就是說childViewControllerForStatusBarStyle和preferredStatusBarStyle方法要想被調用,必須確保前面的vc們都super了(向下modal,不用管下一級,向上dismiss,也不用管本級是否 super)
如果rootVC 不調用super 那么后面的vc都不會調用childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.
從 b dismiss 到 a 到 rootVC的結果如下,都不會調用childViewControllerForStatusBarStyle和preferredStatusBarStyle方法.
navVC沒有 super fourth/fifth也沒有super 一直modal+push到fourth結果如下
修改navVC super 但是fourth/fifth還沒有super 一直modal+push到fourth結果如下
在往下modal fifth 結果如下
從 fifth 往上 dismiss到fourth 結果如下
從 fifth dismiss 到second 結果如下
從 fifth pop到third 結果如下'
從 third dismiss 到 second 結果如下
修改navVC super 但是third
/fourth/fifth還沒有super 一直modal+push到fourth結果如下
和前面third super的調用時一樣的從 fifth dismiss 到 fourth 在pop到third 再dismiss到second 結果如下
和前面third super的調用時一樣的從 fifth dismiss 到 fourth 再dismiss到second 結果如下
和前面third super的調用時一樣的navigationContrller的子控制器 不具備單獨的承接能力,以navigationControllr 的是否super 為準
因此可以在navigationController的這個方法中處理 判斷 比如指定topViewController為某個類的時候,才能采用return self.topViewController,否則return nil-->調用navigationController自己的preferredStatusBarStyle方法
總結一下
View controller-based status bar appearance 默認是 NO,要修改為YES,設置控制的三個方法,才可以生效.一般來說preferredStatusBarStyle方法被調用是因為childViewControllerForStatusBarStyle被調用在先.childViewControllerForStatusBarStyle調用情況是前面的vc們setNeedsStatusBarAppearanceUpdate要super.setNeedsStatusBarAppearanceUpdate方法被調用是rootVC剛顯示和vc被壓棧(壓棧的時候具有追溯性-->rootVC)當vc要被銷毀 三個方法都不走
設置statusBar的【背景部分】1.navigationBar的setBarTintColor接口,用此接口可改變statusBar的背景色 blackColor就是純黑色
2.可以通過以下設置:self.navigationController.navigationBar.barStyle = UIBarStyleBlack將導航條背景樣式設為黑色 不是純黑
會導致setNeedsStatusBarAppearanceUpdate調用兩次
正常是只調用1次的 在modal出navigationController的時候
在navigationController子控制器中強調child方法不會繼續調用prefer方法的.
在navigationController子控制器中強調prefer方法不會生效改變狀態欄的顏色,動一下鍵盤還會調用兩遍navVC的childViewControllerForStatusBarStyle 和preferredStatusBarStyle 方法
參考文章:
https://my.oschina.net/shede333/blog/304560
http://www.lxweimin.com/p/25e9c1a864be
http://www.lxweimin.com/p/ee1c9c91a477
http://www.lxweimin.com/p/fa8d87625906
http://stackoverflow.com/questions/19022210/preferredstatusbarstyle-isnt-called/19513714#19513714
http://stackoverflow.com/questions/17678881/how-to-change-status-bar-text-color-in-ios-7#comment28947732_17768797
http://stackoverflow.com/questions/17678881/how-to-change-status-bar-text-color-in-ios-7