對OS開發(fā)人員來講i, 根據(jù)需求修改狀態(tài)欄的背景的很常見的事情
在 iOS 13之前劈伴,修改狀態(tài)欄的背景顏色的方法很簡單
+ (void)setStatusBarBackgroundColor:(UIColor *)color {? ??
? ? ? ? ?UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]; ??
? ? ? ? ? if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) { ? ? ??
? ? ? ? ? statusBar.backgroundColor = color; ? ? ?
? ? ? ? ? }
}
但是系統(tǒng)升級到iOS 13 之后氢妈,私有KVC??iOS不允許valueForKey非竿、setValue: forKey獲取和設(shè)置私有屬性
坑一:這個時候修改狀態(tài)欄(電池欄的)在用之前的方法會閃退
解決辦法:適配iOS 13? 增加代碼
+ (void)setStatusBarBackgroundColor:(UIColor *)color {
? ? if(@available(iOS13.0, *)) {
? ? ? ? ? ?UIView*?statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
? ? ? ? ? ? [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
? ? ? ? ? ?statusBar.backgroundColor= color;
? ? ? ? }?else?{
? ? ? ? ? ? statusBar.backgroundColor= color;
? ? ? ? }
? ? }else{
? ? ? ? UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
? ? ? ? if([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
? ? ? ? ? ? statusBar.backgroundColor= color;
? ? ? ? }
? ? }
}
坑2:如果整個項目的狀態(tài)欄(電池欄)都是有顏色的型豁,并且都是不透明的,上面這個方法完全可以應(yīng)付
但是:如果有狀態(tài)是有透明或者半透明的效果互纯,上面這個方法還是不能勝任瑟幕,越透明越明顯;經(jīng)過一番查找留潦,終于發(fā)現(xiàn)問題:
問題: iOS 13之前只盹,可以通過valueForKey 獲取UIApplication的statusBar,因為UIApplication是單例兔院,因此殖卑,在iOS 12,通過:?[[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]拿到的statusBar永遠(yuǎn)是同一個對象坊萝。不行可以打印出內(nèi)存地址看下就很清楚了孵稽。iOS 13之后许起,因為蘋果不允許使用KVC的valueForKey訪問私有屬性。通過上面的代碼可以多看點肛冶,每次進(jìn)來都調(diào)用?alloc:init的方法街氢,重新生成一個statusBar;然后添加到UIApplication的keyWindow上睦袖,再設(shè)置背景顏色。因此這個方法多次調(diào)用就會創(chuàng)建多份statusBar荣刑,造成內(nèi)存開銷不說馅笙,如果設(shè)置為透明,根部不能起開效果厉亏。
解決辦法:既然定位到問題所在董习,辦法就是保證iOS 13 之后,每次也都能拿到有去只有一個對象爱只。方法有很多皿淋,我的方法代碼如下:使用 static? 配合 gcd
+ (void)setStatusBarBackgroundColor:(UIColor *)color {
? ? if(@available(iOS13.0, *)) {
? ? ? ? staticUIView*statusBar =nil;
? ? ? ? if(!statusBar) {
? ? ? ? ? ? staticdispatch_once_tonceToken;
? ? ? ? ? ? dispatch_once(&onceToken, ^{
? ? ? ? ? ? ? ? statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
? ? ? ? ? ? ? ? [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
? ? ? ? ? ? ? ? statusBar.backgroundColor= color;
? ? ? ? ? ? });
? ? ? ? }else{
? ? ? ? ? ? statusBar.backgroundColor= color;
? ? ? ? }
? ? }else{
? ? ? ? UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
? ? ? ? if([statusBarrespondsToSelector:@selector(setBackgroundColor:)]) {
? ? ? ? ? ? statusBar.backgroundColor= color;
? ? ? ? }
? ? }
}