How to gracefully adapt dark mode in Swift

References:

  • Swift to judge the system version number of several methods
  • IOS13 – Night Mode/Dark Mode

Dynamic color

From iOS13 onwards, the UIColor class has added the following methods:

extension UIColor {    
    @available(iOS 13.0.*)
    public init(dynamicProvider: @escaping (UITraitCollection) - >UIColor)
}
Copy the code

We can use this method to create dynamic colors, but always use it based on the iOS version number.

To avoid trouble, I wrote a ColorUtil class

class ColorUtil {
  public class func dynamicColor(dark:UIColor.light:UIColor) - >UIColor {
		if #available(iOS 13.*) {  // The version number is greater than or equal to 13
      return UIColor { (traitCollection: UITraitCollection) - >UIColor in
        return traitCollection.userInterfaceStyle = = UIUserInterfaceStyle.dark ?
                      dark : light
      }
    }
    return light
  }
}
Copy the code

Listen for mode changes

Can use the following UIViewController. TraitCollectionDidChange to listen:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?). {
    if #available(iOS 13.*) {
        if self.traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
            if self.traitCollection.userInterfaceStyle = = .dark {
                // Night mode
            } else {
                // Daytime mode}}}}Copy the code

Set the dynamic color of the NavigationBar

There are two ways to modify the NavigationBar style:

  • Modify theNavigationBar.backgroundColor
  • throughNaivgationBar.setBackgroundImage(UIImage? , for: UIBarMetrics)Setting the background image

If the method of modifying backgroundColor is used, the background image will be overlaid, so we need to consider setting the background image to nil, that is:

self.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
self.navigationController?.navigationBar.backgroundColor = yourDynamicColor
Copy the code

If you use the method of modifying the background image, you cannot use dynamic colors, but should modify the background image dynamically in traitCollectionDidChange.