3

I'm using Swift 5.1 and Xcode 11.1 and I've currently finished implementing Dark Mode design.

Theme updates immediately after user changes theme style in settings page with this code.

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
   return
}
appDelegate.changeTheme(themeVal)

// App Delegate File
...
func changeTheme(themeVal: String) {
   if #available(iOS 13.0, *) {
       switch AppState.appThemeStyle {
       case "dark":
           window?.overrideUserInterfaceStyle = .dark
           break
       case "light":
           window?.overrideUserInterfaceStyle = .light
           break
       default:
           window?.overrideUserInterfaceStyle = .unspecified
       }
   }
}

But the problem is that I can't see status bar text because status bar text color and view color is same.

Could anyone please suggest me good solution? Thanks.

Ioan Moldovan
  • 2,272
  • 2
  • 29
  • 54

1 Answers1

9

Status bar color is not global (by default) and if you set that to not ViewControllerBased, you can't change it anymore. So you need to change set it inside any view you need like this:

var statusBarStyle = UIStatusBarStyle.default { didSet { setNeedsStatusBarAppearanceUpdate() } }
override var preferredStatusBarStyle: UIStatusBarStyle { statusBarStyle }

these two variables help you to change the status bar. Note that you can call setNeedsStatusBarAppearanceUpdate inside an animation block to make it animatable.

to detect when UserInterfaceStyle change (and update statusBar color accordingly), all views and viewControllers have delegate function for that. So knowing that:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
        updateStatusBarColor()
    }
}

And this is the function:

func updateStatusBarColor() {
    switch traitCollection.userInterfaceStyle {
    case .unspecified: statusBarStyle = .default
    case .light: statusBarStyle = .darkContent
    case .dark: statusBarStyle = .lightContent
    }
}

Note that:

the ParentViewController defines the statusBarColor. So if you are using general navigationController or tabBarController, A custom class for them with these codes should be enough.

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278