Change Status Bar Background Color in Swift 3
Asked Answered
F

16

66

In XCode 7.3.x ill changed the background Color for my StatusBar with:

func setStatusBarBackgroundColor(color: UIColor) {
guard  let statusBar = UIApplication.sharedApplication().valueForKey("statusBarWindow")?.valueForKey("statusBar") as? UIView else {
    return
}
statusBar.backgroundColor = color
}

But it seems that this is not working anymore with Swift 3.0.

Ill tried with:

func setStatusBarBackgroundColor(color: UIColor) {
guard  let statusBar = (UIApplication.shared.value(forKey: "statusBarWindow") as AnyObject).value(forKey: "statusBar") as? UIView else {
    return
}
statusBar.backgroundColor = color
}

But it gives me:

this class is not key value coding-compliant for the key statusBar.

Any Ideas how to change it with XCode8/Swift 3.0?

Frey answered 1/10, 2016 at 2:28 Comment(0)
W
158
extension UIApplication {
    var statusBarView: UIView? {
        if responds(to: Selector(("statusBar"))) {
            return value(forKey: "statusBar") as? UIView
        }
        return nil
    }
}

UIApplication.shared.statusBarView?.backgroundColor = .red

Update for iOS 13

App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.

Refer to How to change the status bar background color and text color on iOS 13?

Winebibber answered 1/10, 2016 at 2:57 Comment(9)
This isn't a good practice at all, I highly discourage to use this method since this UIView is private. I am curious to see if your app gets approved using this.Georgiegeorgina
@Georgiegeorgina Why isn't this good practice. The method value(forKey key: String) is open so I'm assuming its ok to use. Can you please explain. If this is bad practice, how would you change the background color or the status bar. This methd has worked for me. I've tried adding a subview to the window object in the AppDelegate and that didn't work.Abaxial
@Abaxial using the value(forKey key: String) method you are using the KVC of objc runtime to access a view you shouldn't have access to (and has no documentation referring to it BTW) during runtime only. This construction is used under iOS 10 but not under iOS 9 for instance (where you need to access the statusBarWindow first), and you have absolutely no clue that it will persists under iOS 11. Internal construction and no docs means that Apple does not have any contract to respect here.Georgiegeorgina
Did anyone face app rejection by using this code? or it is safe to use?Eleusis
@SanketBhavsar I have not faced a rejection for using it as of yetWinebibber
I have problem with this method on iPhone X. The background color becomes transparent when app switcher (home indicator) gesture is activated.Monandry
keyWindow is deprecated in iOS 13.Oder
UIApplication.shared.statusBarUIView?.backgroundColor = .whiteRegression
Doesn't work on xcode12. App crashes with, Thread 1: "App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead."Ammunition
L
65

"Change" status bar background color:

let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
let statusBarColor = UIColor(red: 32/255, green: 149/255, blue: 215/255, alpha: 1.0)
statusBarView.backgroundColor = statusBarColor
view.addSubview(statusBarView)

Change status bar text color:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

Update: please note that the status bar frame will change when the view is rotated. You could update the created subview frame by:

  • Using the autoresizing mask: statusBarView.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
  • Observing NSNotification.Name.UIApplicationWillChangeStatusBarOrientation
  • Or overriding viewWillLayoutSubviews()
Lorielorien answered 6/4, 2017 at 19:51 Comment(2)
UIApplication.shared.statusBarUIView?.backgroundColor = .whiteRegression
@JainilPatel invalidTights
P
31

With using Swift 3 and 4 you can use the code snippet on below. It finds the view from UIApplication using valueForKeyPath as set it's background color.

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

Objective-C

UIView *statusBarView = [UIApplication.sharedApplication valueForKeyPath:@"statusBarWindow.statusBar"];
if (statusBarView != nil)
{
    statusBarView.backgroundColor = [UIColor redColor];
}
Pontias answered 10/8, 2018 at 14:2 Comment(0)
D
9

For Xcode 9 and iOS 11: The style of the status bar we will try to achieve is a status bar with white content. Go to the ViewController.swift file and add the following lines of code.

override var preferredStatusBarStyle: UIStatusBarStyle {

     return .lightContent

}

Or from project settings option you can change status bar's style:

enter image description here

Next, go back to the Storyboard, Select the View Controller and in the Editor menu Select Embed in Navigation Controller. Select the Navigation Bar and in the Attribute Inspector set the Bar Tint color to red. The Storyboard will look like this. enter image description here

Build and Run the project, The content of the status bar is dark again, which is the default. The reason for this is, iOS asked for the style of the status bar of the navigation controller instead of the contained view controller.

enter image description here

To change the style of all navigation controller inside the app, change the following method in the AppDelegate.swift file.

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    UINavigationBar.appearance().barStyle = .blackOpaque
    return true
    }

Build and Run the Project again, this time the content of the status bar changed to white.

enter image description here

Damned answered 4/2, 2018 at 6:8 Comment(1)
<3 @Satnam SyncDamned
M
7

I have a custom solution for changing status bar on iOS 13 and below. Here is how to do that:

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

   let statusbarView = UIView()
   statusbarView.backgroundColor = UIColor.red
   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
}

Gist

Also, check the article iOS 13 How to Change StatusBar Color?

One last thing, you can still change statusbar style with :

 override var preferredStatusBarStyle : UIStatusBarStyle {
    return UIStatusBarStyle.lightContent
    //return UIStatusBarStyle.default   // Make dark again
}
Methuselah answered 29/9, 2019 at 11:15 Comment(1)
Underrated solution. Thumbs upMoneyer
K
5

For iOS 11 and Xcode 9 use the following steps.

  1. create an extention to UIApplication class:

    extension UIApplication { var statusBarView: UIView? { return value(forKey: "statusBar") as? UIView } }

  2. In your class or wherever you want to change the Status bar's background color:

    UIApplication.shared.statusBarView?.backgroundColor = .red

  3. For light content or dark content of status bar simply go to Info.plist and add the following value row with value NO.

View controller-based status bar appearance

  1. Now just set the light content or whatever you need in the General Tab of your project's settings.
Kamacite answered 17/2, 2018 at 17:33 Comment(0)
A
4
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any] ?) -> Bool {
    // Override point for customization after application launch.

    UINavigationBar.appearance().barStyle = .blackOpaque
    return true
}

This works for me, as my navigation barTintColor was black and unable to see the status bar.

When set above code it didFinishLaunch status bar appears in white.

Atoll answered 13/6, 2018 at 9:7 Comment(0)
R
4

write this in first view controller:

UIApplication.shared.statusBarUIView?.backgroundColor = .white






extension UIApplication {
    var statusBarUIView: UIView? {
        if #available(iOS 13.0, *) {
            let tag = 38482458385
            if let statusBar = self.keyWindow?.viewWithTag(tag) {
                return statusBar
            } else {
                let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
                statusBarView.tag = tag

                self.keyWindow?.addSubview(statusBarView)
                return statusBarView
            }
        } else {
            if responds(to: Selector(("statusBar"))) {
                return value(forKey: "statusBar") as? UIView
            }
        }
        return nil
    }
}
Regression answered 10/2, 2020 at 12:4 Comment(3)
'keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenesAlmallah
When i wrote the answer i was learning shift language. So it is too old answer.Regression
no worries. Just letting future internet dwellers know that iOS has changed how this works. Currently I'm using this solution: gist.github.com/eonist/ffc0788c57d620aac43ae15cec4b00a9Almallah
P
3

I made this extension to change color of status bar. It's not dependent on the key. So it is much safer to use

public extension UIViewController {
    func setStatusBar(color: UIColor) {
        let tag = 12321
        if let taggedView = self.view.viewWithTag(tag){
            taggedView.removeFromSuperview()
        }
        let overView = UIView()
        overView.frame = UIApplication.shared.statusBarFrame
        overView.backgroundColor = color
        overView.tag = tag
        self.view.addSubview(overView)
    }
}

Here is usage anywhere in viewcontroller:

setStatusBar(color: .red)

Pentecostal answered 9/8, 2019 at 7:45 Comment(1)
Its is not working properly with iPhone X devices . It cover only half of status bar.Bartle
A
2

Try this

Goto your app info.plist

  1. Set View controller-based status bar appearance to NO
  2. Set Status bar style to UIStatusBarStyleLightContent

Then Goto your app delegate and paste the following code where you set your Windows's RootViewController.

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
    UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 20)];
    view.backgroundColor=[UIColor blackColor];
    [self.window.rootViewController.view addSubview:view];
}
Aristophanes answered 1/10, 2016 at 3:26 Comment(1)
Statusbar, not NavigationBar.Frey
W
1

Previous Code:-

func setStatusBarBackgroundColor(color: UIColor) {
        guard let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else { return }

        statusBar.backgroundColor = color
    }

My application got a crash show reason: 'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.'

Updated Code-

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

This code is working swift 5.2

enter image description here

Westbound answered 1/10, 2020 at 4:50 Comment(1)
what is statusBarView?Pollypollyanna
S
0

You can set background color for status bar during application launch or during viewDidLoad of your view controller.

extension UIApplication {

    var statusBarView: UIView? {
        return value(forKey: "statusBar") as? UIView
    }

}

// Set upon application launch, if you've application based status bar
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
        return true
    }
}


or 
// Set it from your view controller if you've view controller based statusbar
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
    }

}



Here is result:

enter image description here

Surmullet answered 13/6, 2018 at 9:16 Comment(3)
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.'Almallah
@Almallah - I tested and posted this answer 3 years back. You are welcomed to update this answer and improve its quality to make it aligned with latest technological changes in Swift/iOS.Surmullet
Yepp. My comment is intended to warn people that are trying to solve this too look else where as it wont work anymore. I got it working now but it requires a lot of research as no-one has it worked out on StackOverflow yet. Here is the solution that is working for iOS 15. (its not elegant at all) gist.github.com/eonist/ffc0788c57d620aac43ae15cec4b00a9Almallah
H
0

The possible solution is adding view that will be used as background of statusBar on your viewController:

let frame = screenController.view.convert(UIApplication.shared.statusBarFrame, to: screenController.view)
let backview = UIView(frame: frame)

backview.backgroundColor = backgroundColor
screenController.view.addSubview(backview)
screenController.view.bringSubviewToFront(backview)
Hentrich answered 15/1, 2019 at 13:11 Comment(2)
This one crash in Swift 5Pollypollyanna
@AlessandroOrnano here is the best solution https://mcmap.net/q/119583/-change-status-bar-background-color-in-swift-3Smalls
B
0

Add following code in your extension file to edit your status bar in swift 4 and Above:

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

now, we can edit status bar by adding following line in our ViewController class:

UIApplication.shared.statusBarView?.backgroundColor = <Your Color name>

ex: UIApplication.shared.statusBarView?.backgroundColor = .red

Hope, this will be helpful. Thanks

Byandby answered 25/3, 2019 at 6:10 Comment(0)
L
0

IOS 15, Xcode 13.2.1, Swift 5

I was able to get this to work without errors or warnings using the following:

func statusBarColor() {
    if #available(iOS 13.0, *) {
        
        let statusBar2 =  UIView()
        if UIApplication.shared.currentScene?.statusBarManager!.statusBarFrame != nil {
            statusBar2.frame = (UIApplication.shared.currentScene?.statusBarManager!.statusBarFrame)!
            statusBar2.backgroundColor = UIColor.init(named: "BackGroundColor")
            UIApplication.shared.windows.first?.addSubview(statusBar2)
        }
    } else {
        let statusBar2: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
        statusBar2.backgroundColor = UIColor.init(named: "BackGroundColor")
    }
}

Use: Call the function in viewDidLoad for single scene applications or applications with only a single statusBar color change needed. For applications with multiple scenes calling for different statusBar colors I recommend calling the function in viewWillAppear.

Lasser answered 19/1, 2022 at 3:2 Comment(0)
S
0

All the solution are outdated. After doing research for about 3 hours, Here is the best solution for all iOS versions in Swift 5.5

I am making an extension of UIViewController which will be easy to use on any viewController.

// MARK: Change status bar color
extension UIViewController {
    public func setStatusBarBackgroundColor(_ color: UIColor) {
        if #available(iOS 13.0, *) {
            // get the window scene and status bar manager for iOS>13.0
            guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                  let statusBarManager = windowScene.statusBarManager
            else {
                return
            }
            // get the status bar height
            let statusBarHeight: CGFloat = statusBarManager.statusBarFrame.size.height

            let statusbarView = UIView()
            // change your color
            statusbarView.backgroundColor = color
            view.addSubview(statusbarView)
            statusbarView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                statusbarView.topAnchor.constraint(equalTo: view.topAnchor),
                statusbarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                statusbarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                statusbarView.heightAnchor.constraint(equalToConstant: statusBarHeight)
            ])
        } else {
            let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
            statusBar?.backgroundColor = color
        }
    }
}

If you have any confusion please let me know. Also if you want to change status bar color according to view controller then follow this step

first changethe "View controller-based status bar appearance" key in the Info.plist, make sure it is set to "YES" like below picture enter image description here

and add this code.

  override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

Note The preferredStatusBarStyle property won't get called if the view controller is embedded in another container view controller, e.g., UINavigationController.

so, you have to assign like this

class YourNavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

And If you want a navigation controller to give control of the status bar style to its children, override the childForStatusBarStyle property and return any child view controllers that you want to determine the status bar style.

override var childForStatusBarStyle: UIViewController? {
    return visibleViewController
}

Chuck this code in your YourNavigationController class.

Best up luck!!!

Smalls answered 4/7, 2023 at 6:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.