For some reason the status bar is not updating the content (.lightContent) in iOS13. It takes like a second to actually update. It is working correctly on iOS12.
I have added View controller-based status bar appearance in the info.plist
My Code:
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UINavigationBar.appearance().isTranslucent = false
navigationController?.navigationBar.barTintColor = UIColor.darkGray
setNeedsStatusBarAppearanceUpdate()
}
override public var preferredStatusBarStyle: UIStatusBarStyle {
//Override all Bool
if (self.view.backgroundColor?.isLight())! {
return .default
} else {
return .lightContent
}
}
overrideUserInterfaceStyle = .dark
matt commented to override the interface style, I do not have enough rep to add a comment, but this is a way to override to dark mode. Another possibility is that there is an issue with self.view.backgroundColor?.isLight()and your background color.
Related
How can I change the back button of a certain navigation controller. I have tried to use
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.backBarButtonItem?.tintColor = UIColor.red
}
I know that if i use navigationController it will change the back button tint color on all of my view controllers.
Try this!!
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.tintColor = .red
}
override func willMove(toParent parent: UIViewController?) {
self.navigationController?.navigationBar.tintColor = // original color
}
}
I've tried adding key UIViewControllerBasedStatusBarAppearance to true inside info.plist file and then added the below code inside UINavigationController class which holds several UIViewController classes.
class HomeNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
But, it did not work.
I've also tried setting the barStyle property of navigationBar to .black but that too didn't work either.
Also looked up to https://stackoverflow.com/a/58203998/9180494, but that did not help as well.
Please NOTE: For UIViewController classes not embedded inside any UINavigationController , if I use computed property preferredStatusBarStyle, then it works.
Try in viewDidAppear() of UINavigationController class:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.navigationBar.barStyle = .black
}
Also add (in the same class as above):
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
#Anuranjan Bose Try this on your view did load,
override func viewDidLoad() {
super.viewDidLoad()
setNeedsStatusBarAppearanceUpdate()
}
I am trying to change the UIStatusBar tint color in a specific UIViewController.
Here is my code:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.setNeedsStatusBarAppearanceUpdate()
}
Nothing is happening.
On a UINavigationController, preferredStatusBarStyle is not called because its topViewController is preferred to self. So, to get preferredStatusBarStyle called on an UINavigationController, you need to change its childViewControllerForStatusBarStyle.
To do it for one UINavigationController:
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
You can add an extension to UINavigationController:
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return visibleViewController
}
}
Then for view controllers that you want a light status bar (white time, icons etc.), then override preferredStatusBarStyle:
override var preferredStatusBarStyle: UIStatusBarStyle {
return UIStatusBarStyle.lightContent
}
For a dark status bar, you don't have to do anything.
You may need to add "View controller-based status bar appearance" with a value of "YES" in your info.plist
I'm working on a swift app and I wanna change the UIStatusBarStyle according to the app's theme (there are 2 options - light and dark theme). I have set View controller-based status bar appearance to NO in the info.plist and in the UIViewController I tried to set it based on the current theme like so:
override var preferredStatusBarStyle: UIStatusBarStyle {
return Theme.current.statusBarStyle
}
protocol ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle { get }
}
class Theme {
static var current: ThemeProtocol = LightTheme()
}
class LightTheme: ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle = .default
}
class DarkTheme: ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle = .lightContent
}
No result really. I tried to test it by returning only: return .lightContent but that didn't change the status bar either.
What am I doing wrong?
UPDATE:
Okay, so this is what I'm trying to do and it's not working.
fileprivate func applyTheme() {
statusBarStyle = UserDefaults.standard.bool(forKey: SelectedThemeKey) ? .default : .lightContent
self.setNeedsStatusBarAppearanceUpdate()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return statusBarStyle
}
And it's not working. Despite changing the theme, the status bar always remain with the default style. applyTheme() is called in viewDidLoad() and viewWillAppear()
You need to call this method after any change
setNeedsStatusBarAppearanceUpdate()
//
class ViewController: UIViewController {
var current = UIStatusBarStyle.default
#IBAction func changeClicked(_ sender: Any) {
current = current == .default ? .lightContent : .default
self.setNeedsStatusBarAppearanceUpdate()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return current
}
}
First of all, your code makes no sense. You say
I have set View controller-based status bar appearance to NO in the info.plist and in the UIViewController I tried to set it
So on the one hand you tell the runtime, do not listen to my view controller. Then you complain when the runtime doesn't listen to your view controller!
Second, keep in mind that your view controller gets no say in the status bar appearance unless it is the top-level view controller (or the top-level view controller deliberately defers to it). If your view controller is inside a navigation controller, for example, its statusBarStyle is completely irrelevant.
First
if you are trying to change StatusBarStyle with UIApplication.shared.statusBarStyle = .default, then you should set
View controller-based status bar appearance to be NO.
in this way, you need to control UIApplication.shared.statusBarStyle by yourself in everywhere; e.g viewWillAppear / viewWillDisappear.
but this method is deprecated after iOS 9.
Now I suggest you learn the new way:
please set View controller-based status bar appearance to be YES, and
override UIViewController's preferredStatusBarStyle to handle it.
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
but it still not working, why?
in your case, I guess that UIViewController is one of viewControllers of UINavigationController.
if you used UINavigationController, you should override preferredStatusBarStyle in UINavigationController.
maybe you will say that I need to set different status bar style with difference view controllers, it is okay.
Just override childForStatusBarStyle in UINavigationController like this
override var childForStatusBarStyle: UIViewController? {
return topViewController
}
then override preferredStatusBarStyle in UIViewController you want to change.
you can also make it by extension like this
extension UINavigationController {
override open var childForStatusBarStyle: UIViewController? {
return topViewController
}
}
Where and how do I have to reset hidesBarsOnSwipe? I set the option in a View Controller which I push and want to reset it for the View Controller which did the push. What I tried until now is setting hidesBarsOnSwipe to false in the viewDidDisappear and in the viewDidLoad of the pushing ViewController.
The Navigationbar is still disappearing.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (!visiblePOIs.isEmpty) {
let beaconInfo = visiblePOIs[indexPath.item]
var controller = storyboard!.instantiateViewControllerWithIdentifier("DetailController")! as! DetailController
controller.setup(beaconInfo)
self.parentViewController!.navigationController?.pushViewController(controller, animated: true)
}
}
DetailController
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
navigationController?.hidesBarsOnSwipe = true
self.automaticallyAdjustsScrollViewInsets = false
}
next view controller write in viewDidload
First Vc
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.hidesBarsOnSwipe = true
}
Second VC
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.hidesBarsOnSwipe = false
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
I hope its works
I had your exact problem. Here's how I solved it. (You can adapt this based on your needs.)
class MyViewController: UITableViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//Correct the nav bar state unwinding from segues
self.navigationController?.hidesBarsOnSwipe = true
}
override func willMoveToParentViewController(parent: UIViewController?) {
super.willMoveToParentViewController(parent)
//Toggle the auto-hiding nav bar when this view gets added/removed from the nav controller
self.navigationController?.hidesBarsOnSwipe = !self.navigationController!.hidesBarsOnSwipe
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
//Reset the nav bar to visible when segueing to another view
self.navigationController?.navigationBarHidden = false
self.navigationController?.hidesBarsOnSwipe = false
}
}
This approach allows you to limit the functionality of the auto-hiding feature to the desired view controller without adding code to all associated view controllers.