Using TabbarViewController the preferredStatusBarStyle not called - swift

I have a TabbarViewController with different views, the problem is:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
not called in any the of the views.
I have tried to add:
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return selectedViewController?.childForStatusBarStyle ?? selectedViewController
}
}
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return topViewController?.childForStatusBarStyle ?? topViewController
}
}
Nothing change, should I call this extension method in some where else?

You could try to add in to Info.plist expect adding some codes.
You can basically add this into your Info.plist

I had to create a class of UInavigation Controller then add this methods to the class and it start to work.
override open var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
override open var preferredStatusBarStyle : UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}

Related

Lock device orientation for SwiftUI UIViewControllerRepresentable

I have a UIViewController that I need to wrap and use as a SwiftUI view. I have implemented the methods needed to lock device orientation for that view controller. When I use the UIViewController in an UIKit context, the orientation could be locked.
class ContentViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.red
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
override var shouldAutorotate: Bool {
return false
}
}
When I wrap it as a SwiftUI view with UIViewControllerRepresentable, the orientation could not be locked. The
struct ContentWrappedView : UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> ContentViewController {
return ContentViewController.init()
}
func updateUIViewController(_ uiViewController: ContentViewController, context: Context) {
}
}
Is this expected behavior? Is there a way around it?
I'll be using it in a framework and so, implementing it with AppDelegate doesn't work for me. Thanks in advance.

What is the correct way to manage statusBarStyle in Swift?

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()
}

Attempting to Change the UIStatusBar Tint Color

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

UIStatusBarStyle doesn't change

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
}
}

extension for UIViewController is not Working change UIStatusBarStyle In Swift

I am Try to Create extension for UIViewController but Its not working . i am changing status bar color for using extension but i cant get success. But without extension is working. I am new in Extension Please help me.
My Aim is I DONT WANT TO CREATE FUNCTION ON EVERY VIEW CONTROLLER , REDUSE REUSABILITY
Create Extension Is Not Working
extension UIViewController {
func preferredStatusBarStyle_change() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
}
//!!!!!!!!!view1
override func viewDidLoad() {
super.viewDidLoad()
//preferredStatusBarStyle();
self.preferredStatusBarStyle_change();
}
//!!!!!!!!!view2
override func viewDidLoad() {
super.viewDidLoad()
//preferredStatusBarStyle();
self.preferredStatusBarStyle_change();
}
Without Extension IS Working
View1
override func viewDidLoad() {
super.viewDidLoad()
preferredStatusBarStyle();
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
View2
override func viewDidLoad() {
super.viewDidLoad()
preferredStatusBarStyle();
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
Help me Try to understanding Reusability and extension
It not working because:
Viewcontroller will call preferredStatusBarStyle() for define about statusbar. Actually you remove preferredStatusBarStyle(); in viewDidload, your controller still work.
So in your case you can resolve like this:
You create a subclass of UIViewController maybe name it is: BaseViewController and it this class you put:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
And now all your ViewController you inherited from BaseViewController status bar will always .LightContent you don't need put this code above every where.
Demo: Demo