How to change the status bar background color and text color on iOS 13?
Solution 1
You can add some conditions or use first one. Just create some extension for 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
}
}
}
UPDATED: Sorry, I don't have enough time to test it in real projects, but it works in "Hello world" app. You can read more info about keyWindow and statusBarFrame in order to make it better.
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
}
}
Solution 2
Unfortunately Apple deprecated some of the mentioned methods of accessing the status bar and editing its attributes. You will have to use the StatusBarManager
object of the WindowScene
. The following method works for iOS 13 and above:
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)
}
}
Solution 3
I have encountered this issue before. My application got crash while I run this code using XCode 11 and Swift 5.0.
Previous Code:-
UIApplication.shared.statusBarView?.backgroundColor = UIColor.init(red: 243/250, green: 243/250, blue: 243/250, alpha: 1)
Just Changed to:-
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)
}
Now my problem solved. Happy coding.
Solution 4
for swift 5.0 I've done this to change background color,
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
Solution 5
This worked for me in 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
}
}
Related videos on Youtube
Hugo Alonso
Hi!, A happy human that loves being a coder over here! I'm always eager to improve my skills and explore other points of view. I started to code in C++ & Java, after several languages.., I'm now comfortably stuck with Swift. I'm really curious, so I like to get a grasp of almost every disruptive technology... I guess I'm kind of a technological polygamist 😅. Oh.. I enjoy teaching, I have been a 👨🏻🏫 for several years and through StackOverflow, I have had the opportunity to continue when not in the classroom. ✌🏻
Updated on July 05, 2022Comments
-
Hugo Alonso almost 2 years
With the arrival of iOS 13 statusBar's view is no longer accessible trough:
value(forKey: "statusBar") as? UIView
Due to:
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.'
But it's not clear how it should be used for changing colours as
keyWindow?.windowScene?.statusBarManager
does not appear to contain anything related to it.I'm compiling my code with (iOS 10, *) compatibility, so I intend to continue using UIKit.
Any ideas regarding this subject?
-
rmaddy almost 5 yearsWhy are you trying to manually change the status bar background color? By default it will match the color of your app.
-
Hugo Alonso almost 5 yearsIt's a legacy app that includes a custom status bar colour making it look apart from the rest of the app
-
rmaddy almost 5 yearsThere has never been a valid way to modify the status bar color. Such solutions always end up breaking eventually. Never dig into the private subview structure.
-
Mike almost 5 years@HugoAlonso see my answer here: stackoverflow.com/questions/56556254/…
-
Hugo Alonso over 4 years@rmaddy can you add an answer stating the fact that is not possible and what's the best approach so I can set it as the accepted one?
-
Akshay Jadhav over 4 yearsyoutube.com/watch?v=bZXk0Dwxopw.... refer this video
-
Akshar Darji over 4 years@hugoAlonso You can check this answer: stackoverflow.com/a/57848822/2677134
-
-
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
sandy over 4 yearsSo,how to get statusBarView in OC
-
rmaddy over 4 yearsThere is no statusBarView to get. There is no public API for it. In iOS 13 you can get the statusBarManager from a window scene but there is no view.
-
Hugo Alonso over 4 yearsWhy would you want to use something that's deprecated?
-
Ram G. over 4 yearscan you please add methods - createLocalStatusBar and @selector(statusBar)
-
Lance Samaria over 4 years@isHidden I was using the iOS version with np, updated to Xcode 11 and iOS 13 and got a crash, I checnged the extension code to your answer and no more crashes, thanks. But can you give an example on how to use your code information iOS 12 and iOS 13. Right now it just shows what to add in the extension
-
Preetam Jadakar over 4 yearsas pointed by @rmaddy,
keyWindow
as well asstatusBarFrame
are both deprecated -
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
rmaddy over 4 years
keyWindow
is deprecated in iOS 13. -
rmaddy over 4 yearsThat's better, but it still isn't ideal. What happens when the app is showing two different scenes on an iPad? This code only shows the extra view above one of the scenes and not both.
-
Niki over 4 years@rmaddy So should i put a for loop, and which would execute the same code for all windows ?
-
Steve Brooker over 4 yearsAny chance of someone providing an Objective C version of this?
-
Marlhex over 4 years'statusBarFrame' was deprecated in iOS 13.0: Use the statusBarManager property of the window scene instead.
-
Marlhex over 4 yearsValue of type '[UIWindow]' has no member 'addSubview'
-
Niki over 4 years@Daniella I've updated my code, would you please check your code now!
-
MMK over 4 yearsnew to iOS dev. Can anyone tell me where to use this code snippet? in AppDelegate or viewController?
-
Ajeet over 4 yearslet keyWindow = UIApplication.shared.connectedScenes .filter({$0.activationState == .foregroundActive}) .map({$0 as? UIWindowScene}) .compactMap({$0}) .first?.windows .filter({$0.isKeyWindow}).first You can call directly as:- keyWindow?.addSubview(statusBar)
-
rmaddy over 4 yearsDon't put code in a comment, update your answer as needed. Keep in mind that there may be two active scenes so simply grabbing the first could be wrong.
-
Roman over 4 yearsFor keyWindows: UIApplication.shared.windows.filter {$0.isKeyWindow}.first
-
Alberto Schiariti over 4 years
PorcoDiDio
is deprecated in iOS 13 -
isHidden over 4 years@HugoAlonso, There are no warnings in my projects, maybe the reason is their age.
-
isHidden over 4 years@MMK in my case i use it in viewController to have ability to change the statusBar colour for different VC.
-
isHidden over 4 years@LanceSamaria to change statusBar colour write this in some place of your code. (For example in viewWillAppear or in AppDelegate): UIApplication.shared.statusBarUIView?.backgroundColor = .yellow
-
Lance Samaria over 4 years@isHidden thanks for getting back to me. I figured out how to use it later that day after I asked you. I forgot what I did exactly but maybe it was what you just wrote? Any much appreciated. Happy Coding!
-
Hugo Alonso over 4 yearsWhere is stated that the view is the one with tag 3848245?
-
isHidden over 4 years@HugoAlonso, it works for me. The tag for each subview is 0 by default. But maybe in some case the window can already has a subview with same tag. If you want to be sure that your tag is unique you can do the next: 1) create function that get UIView description and convert it to Int hash value, than use it like a tag to identify your view. 2) create function that generate random integer value and check if there are the same in window, if yes - generate new random value, no - use it like a tag. 3) try to find some docs where is stated that your tag is unique.
-
Patrick over 4 yearsBest answer of all
-
Niki over 4 years@jayantrawat yes, In didFinishLaunchingWithOptions application method within APPDELEGATE.
-
jayant rawat over 4 years@Niki its not working for me with Xcode 11/iOS13 & UIApplication.shared.statusBarView is also not available in Xcode11...
-
Vinayak Bhor about 4 yearsPerfect Solution!
-
Giuseppe Garassino over 3 years'statusBarFrame' was deprecated in iOS 13.0: Use the statusBarManager property of the window scene instead. '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 scenes...
-
D. B. over 3 yearsHow about the check if the statusBar view was added already? This is to make sure we do not add same subview again and again.
-
Artiom over 3 yearsthe problem with this solution is that statusBarFrame is nil in case you call it in viewDidLoad or viewWillAppear. Works only in viewDidAppear what does not sound as a best place to set up UI
-
Ben over 3 yearsIf you are unsure how to call this like I was, in viewDidAppear (thanks @Artiom) call self.navigationController?.setStatusBar(backgroundColor: yourColor) AND self.navigationController?.navigationBar.setNeedsLayout()
-
Ben over 3 yearsAlternatively, you can call self.navigationController?.setStatusBar(backgroundColor: yourColor) in viewWillAppear
-
karthikeyan over 3 yearsHow about notch device?
-
Snapp over 3 yearsIt works on all kind of device even notch device.
-
Admin about 3 years@isHidden, how can I apply it to swiftUI
-
Andy Weinstein almost 3 yearsThis works for me but... (I am making black status bar with white text, working without a NavController). I found that in my first viewController I had to put the code from this answer in viewDidAppear for it to work. In subsequent viewControllers in the flow I put it in viewWillAppear. I am also using this solution - which works for a non-NavController scenario: stackoverflow.com/a/17768797/826946. That makes the statusbar text white. Also not using the pre-OS13 part
-
justdan0227 over 2 yearsI'm getting a warning of : '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 scenes
-
Nilay Dagdemir over 2 years"Value of type 'UIApplication' has no member 'statusBarView'" error occured for Swift 5.
-
David.C over 2 yearsthis is not working.
-
Eduard Streltsov over 2 years@Skysoft13 it's completely different story for SwiftUI. Here's a solution I use stackoverflow.com/questions/62207272/…
-
Eduard Streltsov over 2 yearsIt would be great to see which settings in the attribute inspector were changed, cause when I changed the title background in NavigationController it didn't affect the status bar background
-
Sentry.co over 2 years'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead