overrideUserInterfaceStyle not working in AppDelegate - ios

I'm building an iOS app with the newest version of Xcode.
If I set
overrideUserInterfaceStyle = .light
to a View Controller, it will get set to light mode, also if dark mode is enabled.
But If I put this code in AppDelegate like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window?.overrideUserInterfaceStyle = .light
return true
}
it doesn't work.
There are no errors. The app simply is in light mode or dark mode depending on the mode the device is in.
Why doesn't overrideUserInterfaceStyle work in AppDelegate? Is it because I'm using a Tab Bar Controller for my app? I don't think so.

It's too early to call overrideUserInterfaceStyle in AppDelegate, window is not yet created. You can use SceneDelegate willConnectTo function.

Related

Status Bar Style issues since Xcode 11.4

Since Xcode 11.4 overriding the preferredStatusBarStyle property does not seem to work anymore in some cases.
We have an extension of UINavigationController where we override it for basically every ViewController but this property is no longer called since Xcode 11.4. Therefore the status bar is black for mostly all ViewControllers.
extension UINavigationController {
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
It also stopped working for some ViewControllers where we override preferredStatusBarStyle again. The property gets accessed, however, the status bar does not change its color.
View controller-based status bar appearance is set to YES in info.plist.
Issue occurs on simulator and real devices.
Does anyone have this problem too?
Ok I found a solution. Looks like I need to set the barStyle of the navigationBar to .black as described here
navigationController?.navigationBar.barStyle = .black
Not sure though why this is necessary now.
The UINavigationController extension is no longer needed then.
change the UIStatusBarStyle in appdelegates in this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}

Ios 13 screen brightness problem by swift

I'm working on a project, and I have to control the screen brightness.
I use this to control:
UIScreen.main.brightness = CGFloat(0.80)
But, once I lock the screen and unlock, the screen brightness will change back to the system brightness, which could not go back to the brightness which I set before.
If there is any func I can use to change the screen brightness when users unlock the screen?
Thank you!
There is a method called applicationWillEnterForeground in UIApplicationDelegate which already conforms to your AppDelegate class.
Implement applicationWillEnterForeground by typing name of this method inside your AppDelegate class. like:
you can set the brightness whenever app goes to foreground
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
func applicationWillEnterForeground(_ application: UIApplication) {
UIScreen.main.brightness = CGFloat(0.80)
}
}

Is it possible to change Status Bar color for all view controllers?

I have been searching for a while now and I only found answers that describe to change color on one view controller not for all view controllers.
Is it possible to do it?
Only two steps are needed to change the status bar style for the entire app. 🙂
Step 1
Add a new property to the project's Info.plist file and set it to false.
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
Step 2
Go to your project's target and under General / Deployment Info, switch Status Bar Style from Default to Light.
Doing these steps will ensure the status bar behaves the same in the entire project.
Set the style of the status bar in AppDelegate.swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.statusBarStyle = .lightContent
return true
}
And add the following code to your Info.plist:
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
First in info.plist set View controller-based status bar appearance to NO
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
statusBar.backgroundColor = UIColor.blue
}
UIApplication.shared.statusBarStyle = .lightContent
return true
}
The output screenshot is below
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:
Here is Apple Guidelines/Instruction about status bar change. Only Dark & light (while & black) are allowed in status bar.
Here is - How to change status bar style:
If you want to set status bar style, application level then set UIViewControllerBasedStatusBarAppearance to NO in your `.plist' file.
Or programatically you can do it from app delegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
application.statusBarStyle = .lightContent
return true
}
if you wan to set status bar style, at view controller level then follow these steps:
Set the UIViewControllerBasedStatusBarAppearance to YES in the .plist file, if you need to set status bar style at UIViewController level only.
In the viewDidLoad add function - setNeedsStatusBarAppearanceUpdate
override preferredStatusBarStyle in your view controller.
-
override func viewDidLoad() {
super.viewDidLoad()
self.setNeedsStatusBarAppearanceUpdate()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Set value of .plist according to status bar style setup level.
Swift 4
In AppDelegate.swift add this extension:
extension UINavigationController {
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
Yes,
Step 1:
Open your info.plist and insert a new key named "View controller-based status bar appearance" to NO
Step 2:
Open the viewcontroller file where you want to change the statusBarStyle and put the following code in viewWillAppear(),
UIApplication.shared.statusBarStyle = .lightContent
Step 3 :
Also, implement the viewWillDisappear() method for that specific viewController and put the following lines of code,
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
UIApplication.shared.statusBarStyle = UIStatusBarStyle.default
}
All the best
Important clarification
It is very important to understand two approaches to customizing the status bar.
Is it possible to change Status Bar color for all view controllers?
Boolean answer is Yes, but, in legal way, it is so close to No that answering Yes is provocative if you need colors other that black or white.
There are two approaches when it comes to customizing Status bar appearance.
First approach – one color for whole app
In info.plist you find or create a key called
View controller-based status bar appearance
and set it to NO.
What it does? It essentially establishes a setting that says that in your application, status bar appearance is not defined individually by each view controller. This is super important to understand. This means that you have uniform setting for entire app, for all screens. This is what you needed. But. You are limited to only two settings: white and black. And there's no way you can customize it using documented API.
To set this up:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
application.statusBarStyle = .lightContent
return true
}
Second approach – individual color for each view controller
This is the opposite. To make it work, go ahead to info.plist and set
View controller-based status bar appearance
to YES
This way, whenever a new view controller is open, status bar style is set individually if you insert this implementation in each UIViewController instance you need:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
You have the same as in first, set either dark or light style for statusbar.
Third approach – Hack!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let statusbar = value(forKey: "statusBar") as? UIView {
statusbar.backgroundColor = UIColor.blue
}
return true
}
Why hack? If you need status bar color other than black or white. Here you use undocumented API. You get statusBar object using KVC and manually set its color. This is dirty, not legal way, but so far it's the only way to set up custom color for statusbar. It may well lead your app to being rejected. But maybe you're lucky. In order to set it once and for all, you will need to set to NO the aforementioned flag so that status bar did not initialize its style with each view controller.

iOS App is creating two UIWindow

I was refactoring an existing project to move away from using .storyboards and removed the initial main interface in .plist, but for some reason the app is creating two instances of UIWindow.
I have no idea on why this is happening, and the result of this is when I do create my actual UIWindow and use makeKeyAndVisible() for a second I get a black screen until the actual rootViewController becomes visible, this happens because in that split of a seconds it shows the first UIWindow which color is nil. If someone has any idea on why this is happening I would appreciate a bunch ;)
EDIT 1:
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
appCoordinator.start()
return true
}
AppCoordinator.swift
func start() {
let mainVC = UIStoryboard(storyboard: .main).instantiateInitialViewController()
window.backgroundColor = .white
window.rootViewController = mainVC
window.makeKeyAndVisible()
}
Check that "Main Interface" is empty:

Odd behavior from UITabBar where background color only shows for one tab

I am using Swift 3 and I researched various methods to set the backgroundColor color of a UITabBar. The most simple method was to change the property in the didFinishLaunchingWithOptions of the AppDelegate. When I tried to do this, the UITabBar launches with the standard color, which is not my intended result.
However, when I go to the next tab, the UITabBar color gets changed to my intended color.
Following this, I tried to subclass my UITabBarController and I tried to set the background colors in both the viewDidLoad and in the viewDidLayoutSubViews. All three of these attempts exhibited the exact same behavior - which was the UITabBar launched with the standard color, and only changed colors when I tabbed to the next tab.
Here is my code:
App Delegate
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)
-> Bool {
UITabBar.appearance().backgroundColor = UIColor.red
return true
}
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.backgroundColor = UIColor.red
}
viewDidLayoutSubviews
override func viewDidLayoutSubviews() {
self.tabBar.backgroundColor = UIColor.red
}
My questions are the following:
1) Can I eliminate this as being a constraint issue? I didn't modify or set any constraints for the UITabBar
2) I have a launch screen where the user selects acknowledges something and then they are segued to the UITabBarController. Could this be part of the issue?
The basic way to change to a tab bar's color is not to set its backgroundColor as you are doing, but rather to set its barTintColor. (For more sophisticated control, use a colored backgroundImage.)
Putting this in my app delegate gets me a tab bar that's tinted red.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let tabBarVC = UITabBarController()
tabBarVC.viewControllers = [FirstViewController(), SecondViewController()]
tabBarVC.tabBar.backgroundColor = UIColor.red
window?.rootViewController = tabBarVC
window?.makeKeyAndVisible()
return true
}

Resources