如何在iOS 13上更改状态栏的背景颜色和文本颜色?

时间:2019-06-18 14:18:38

标签: ios swift statusbar ios13

随着 iOS 13 的到来,statusBar的视图不再可以通过槽访问:

value(forKey: "statusBar") as? UIView

由于:

  

由于未捕获的异常而终止应用程序   “ NSInternalInconsistencyException”,原因:“应用程序名为-statusBar或   UIApplication上的-statusBarWindow:由于不再有状态栏或状态栏窗口,因此必须更改此代码。使用   而是在窗口场景上使用statusBarManager对象。'

但是由于keyWindow?.windowScene?.statusBarManager似乎不包含任何与其相关的内容,因此尚不清楚应如何使用它来更改颜色。

我正在编译具有(iOS 10,*)兼容性的代码,所以我打算继续使用UIKit。

关于这个主题有什么想法吗?

15 个答案:

答案 0 :(得分:32)

您可以添加一些条件或使用第一个条件。只需为UIApplication创建一些扩展即可。

extension UIApplication {
var statusBarUIView: UIView? {
    if #available(iOS 13.0, *) {
        let tag = 38482
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

        if let statusBar = keyWindow?.viewWithTag(tag) {
            return statusBar
        } else {
            guard let statusBarFrame = keyWindow?.windowScene?.statusBarManager?.statusBarFrame else { return nil }
            let statusBarView = UIView(frame: statusBarFrame)
            statusBarView.tag = tag
            keyWindow?.addSubview(statusBarView)
            return statusBarView
        }
    } else if responds(to: Selector(("statusBar"))) {
        return value(forKey: "statusBar") as? UIView
    } else {
        return nil
    }
  }
}

更新:对不起,我没有足够的时间在实际项目中对其进行测试,但是它可以在“ Hello world”应用程序中使用。您可以阅读有关keyWindowstatusBarFrame的更多信息,以使其变得更好。

extension UIApplication {
var statusBarUIView: UIView? {

    if #available(iOS 13.0, *) {
        let tag = 3848245

        let keyWindow = UIApplication.shared.connectedScenes
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows.first

        if let statusBar = keyWindow?.viewWithTag(tag) {
            return statusBar
        } else {
            let height = keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
            let statusBarView = UIView(frame: height)
            statusBarView.tag = tag
            statusBarView.layer.zPosition = 999999

            keyWindow?.addSubview(statusBarView)
            return statusBarView
        }

    } else {

        if responds(to: Selector(("statusBar"))) {
            return value(forKey: "statusBar") as? UIView
        }
    }
    return nil
  }
}

答案 1 :(得分:4)

我以前遇到过此问题。当我使用XCode 11和Swift 5.0运行此代码时,我的应用程序崩溃了。

上一个代码:-

if #available(iOS 13.0, *) {
    let statusBar = UIView(frame: UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
     statusBar.backgroundColor = UIColor.init(red: 243/250, green: 243/250, blue: 243/250, alpha: 1)
     UIApplication.shared.keyWindow?.addSubview(statusBar)
} else {
     UIApplication.shared.statusBarView?.backgroundColor = UIColor.init(red: 243/250, green: 243/250, blue: 243/250, alpha: 1)
}

仅更改为:-

return Ok(response);

现在我的问题解决了。编码愉快。

答案 2 :(得分:2)

不幸的是,Apple不赞成使用上述提到的访问状态栏和编辑其属性的方法。您将必须使用StatusBarManager的{​​{1}}对象。以下方法适用于iOS 13及更高版本:

WindowScene

答案 3 :(得分:2)

这在Swift 5中对我有用

   override func viewDidLoad() {
      super.viewDidLoad()

      if #available(iOS 13, *)
      {
          let statusBar = UIView(frame: (UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame)!)
          statusBar.backgroundColor = #colorLiteral(red: 0.2346, green: 0.3456, blue: 0.5677, alpha: 1)
          UIApplication.shared.keyWindow?.addSubview(statusBar)
      } else {
         // ADD THE STATUS BAR AND SET A CUSTOM COLOR
         let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
         if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
            statusBar.backgroundColor = #colorLiteral(red: 0.2346, green: 0.3456, blue: 0.5677, alpha: 1)
         }
         UIApplication.shared.statusBarStyle = .lightContent
      }
   }

答案 4 :(得分:1)

if (@available(iOS 13, *))
{    
    UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
    statusBar.backgroundColor = [UIColor redColor];
    [[UIApplication sharedApplication].keyWindow addSubview:statusBar];

 }

答案 5 :(得分:1)

对于像我这样仍在使用它的人,这是大多数投票答案的ObjC版本:

创建UIApplication的类别并将其添加到您的项目中:

@implementation UIApplication (iOS13PorcoDiDio)

- (UIView*) statusBar
{

    if([UIDevice getOSVersion] >= 13)
    {

        const NSUInteger k_TAG_STATUSBAR = 38482458385;

        UIView * vStatusBar = [[UIApplication sharedApplication].keyWindow viewWithTag:k_TAG_STATUSBAR];
        if(vStatusBar != nil)

            return vStatusBar;

        else {

            UIView *vStatusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame];
            [vStatusBar setTag:k_TAG_STATUSBAR];
            [[UIApplication sharedApplication].keyWindow addSubview:vStatusBar];

            return vStatusBar;

        }

    } else if([UIApplication respondsToSelector:@selector(statusBar)])

        return (UIView*)[UIApplication sharedApplication].statusBar;

    else

        return nil;


}

@end

答案 6 :(得分:1)

"suggest": {
    "name/translation": "Needed to translate localizable texts."
}

} enter image description here 在ios 13中正常工作

答案 7 :(得分:1)

经过测试,并且100%为我工作

func statusBarColorChange(){

    if #available(iOS 13.0, *) {

            let statusBar = UIView(frame: UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
            statusBar.backgroundColor = AppThemeColor
            statusBar.tag = 100
            UIApplication.shared.keyWindow?.addSubview(statusBar)

    } else {

            let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
            statusBar?.backgroundColor = AppThemeColor

        }
    }
}

从键窗口中删除状态栏

func removeStatusBar(){

    if #available(iOS 13.0, *) {

        UIApplication.shared.keyWindow?.viewWithTag(100)?.removeFromSuperview()

    }
}

viewDidLoadviewWillAppear中调用函数

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    removeStatusBar()
    statusBarColorChange()
}

override func viewDidLoad() {
    super.viewDidLoad()

    removeStatusBar()
    statusBarColorChange()

}

答案 8 :(得分:1)

KeyWindow在iOS13中已弃用。 您可以将此扩展名用于 swift 5 iOS 13至顶部

extension UIApplication {

    var statusBarUIView: UIView? {

        if #available(iOS 13.0, *) {
            let tag = 3848245

            let keyWindow: UIWindow? = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

            if let statusBar = keyWindow?.viewWithTag(tag) {
                return statusBar
            } else {
                let height = keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
                let statusBarView = UIView(frame: height)
                statusBarView.tag = tag
                statusBarView.layer.zPosition = 999999

                keyWindow?.addSubview(statusBarView)
                return statusBarView
            }

        } else {

            if responds(to: Selector(("statusBar"))) {
                return value(forKey: "statusBar") as? UIView
            }
        }
        return nil
      }
}

并在 AppDelegate 类的 didFinishLaunchingWithOptions 中使用它,例如:

UIApplication.shared.statusBarUIView?.backgroundColor = .red(any color)

答案 9 :(得分:0)

对于Swift 5.0,我这样做是为了更改背景颜色,

    if #available(iOS 13.0, *) {
           let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first 
           // Reference - https://stackoverflow.com/a/57899013/7316675
           let statusBar = UIView(frame: window?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
           statusBar.backgroundColor = .white
           window?.addSubview(statusBar)
    } else {
           UIApplication.shared.statusBarView?.backgroundColor = .white
           UIApplication.shared.statusBarStyle = .lightContent
    }

https://medium.com/@trivediniki94/surprises-after-upgrading-to-xcode-11-ios-13-b52b36e05fa8

答案 10 :(得分:0)

我认为最简单的方法是使用NavigationController而不是ViewController。使用情节提要更改导航栏背景也会反映在状态栏上

NavigationController

答案 11 :(得分:0)

Use this Extension:

extension UINavigationController {

func setStatusBar(backgroundColor: UIColor) {
    let statusBarFrame: CGRect
    if #available(iOS 13.0, *) {
        statusBarFrame = view.window?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero
    } else {
        statusBarFrame = UIApplication.shared.statusBarFrame
    }
    let statusBarView = UIView(frame: statusBarFrame)
    statusBarView.backgroundColor = backgroundColor
    view.addSubview(statusBarView)
}}

答案 12 :(得分:-1)

您可以尝试

if (@available(iOS 13, *))
{
    UIView *_localStatusBar = [[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager performSelector:@selector(createLocalStatusBar)];
    statusBar = [_localStatusBar performSelector:@selector(statusBar)];
}
else
{
    statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
}

答案 13 :(得分:-1)

我这样做,可以获取statusBar,但设置statusBar backgroundColor不起作用

UIView *statusBar;
if (@available(iOS 13, *)) {
    UIView *_localStatusBar = [[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager performSelector:@selector(createLocalStatusBar)];
    statusBar = [_localStatusBar performSelector:@selector(statusBar)];
}
else {
    statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
}
if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
    statusBar.backgroundColor = [UIColor redColor];
}

答案 14 :(得分:-1)

这是我见过的最好的答案。。干杯

    if #available(iOS 13.0, *) {
    let app = UIApplication.shared
    let statusBarHeight: CGFloat = app.statusBarFrame.size.height

    let statusbarView = UIView()
        statusbarView.backgroundColor = ColorPalette.grayChateau  
    view.addSubview(statusbarView)

    statusbarView.translatesAutoresizingMaskIntoConstraints = false
    statusbarView.heightAnchor
        .constraint(equalToConstant: statusBarHeight).isActive = true
    statusbarView.widthAnchor
        .constraint(equalTo: view.widthAnchor, multiplier: 1.0).isActive = true
    statusbarView.topAnchor
        .constraint(equalTo: view.topAnchor).isActive = true
    statusbarView.centerXAnchor
        .constraint(equalTo: view.centerXAnchor).isActive = true

} else {
    let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
    statusBar?.backgroundColor = UIColor.red
 }