iOS 13 设置状态栏背景的颜色的坑

对OS开发人员来讲i, 根据需求修改状态栏的背景的很常见的事情

在 iOS 13之前,修改状态栏的背景颜色的方法很简单

+ (void)setStatusBarBackgroundColor:(UIColor *)color {    

         UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];   

          if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {       

          statusBar.backgroundColor = color;      

          }

}

但是系统升级到iOS 13 之后,私有KVC  iOS不允许valueForKey、setValue: forKey获取和设置私有属性

坑一:这个时候修改状态栏(电池栏的)在用之前的方法会闪退

解决办法:适配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:如果整个项目的状态栏(电池栏)都是有颜色的,并且都是不透明的,上面这个方法完全可以应付

但是:如果有状态是有透明或者半透明的效果,上面这个方法还是不能胜任,越透明越明显;经过一番查找,终于发现问题:

问题: iOS 13之前,可以通过valueForKey 获取UIApplication的statusBar,因为UIApplication是单例,因此,在iOS 12,通过: [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]拿到的statusBar永远是同一个对象。不行可以打印出内存地址看下就很清楚了。iOS 13之后,因为苹果不允许使用KVC的valueForKey访问私有属性。通过上面的代码可以多看点,每次进来都调用 alloc:init的方法,重新生成一个statusBar;然后添加到UIApplication的keyWindow上,再设置背景颜色。因此这个方法多次调用就会创建多份statusBar,造成内存开销不说,如果设置为透明,根部不能起开效果。

解决办法:既然定位到问题所在,办法就是保证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;

        }

    }

}


你可能感兴趣的:(iOS 13 设置状态栏背景的颜色的坑)