Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compatibility of named colors below iOS 11

I need to implement the dark mode in my iOS app which runs on iOS 8+. Also I have custom colors defined in color assets with RGB codes for both light and dark appearance.

The problem is named colors are not supported proir to iOS 11, but I can use only named colors to support both appearances - dark and light.

Is there any way to implement a backward compatibility?

like image 798
Artem Mostyaev Avatar asked Dec 06 '19 13:12

Artem Mostyaev


1 Answers

You can't do it while using color assets. However you can create your own ThemeManger to handle the app's theme.

First create a ThemeManager. It's main purpose is to hold the style of the app.

class ThemeManager {

    static let shared: ThemeManager = ThemeManager()

    var style: ThemeStyle = .light 
}

Here ThemeStyle should be an enum containing your themes(light, dark etc.).

Create a ThemeColor class to handle your colors

class ThemeColor {
    var dark: UIColor = UIColor.clear
    var light: UIColor = UIColor.clear
    var asset: String = ""    

    func getColor(for theme: ThemeStyle = ThemeManager.shared.style) -> UIColor {
        if #available(iOS 13.0, *) {
            if asset != "", let assetColor = UIColor(named: asset) {
                return assetColor
            }
        }
        if theme == .dark {
            return dark
        }

        return light
    }
}

You can use the getColor function to get required color. Notice that ThemeColor returns the asset color value for iOS 13. This is for changing the app's theme when user changes his/her preference from settings.

Example:


extension UIColor {
    class var backgroundColor: ThemeColor {
        let themeColor = ThemeColor()
        themeColor.light = UIColor.white
        themeColor.dark = UIColor.black
        themeColor.asset = "backgroundColor"

        return themeColor
    }
}

// Somewhere in your code set the backgroundColor of your view
myView.backgroundColor = UIColor.backgroundColor.getColor()

  • To make this work you need to update your style variable in ThemeManger based on user's preference for iOS 13 devices. You can do this by traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) implementing this method in your UIViewController class.
  • Just like the backgroundColor example you need to define all your colors which are effected by the theme change.
  • Set the style value of your ThemeManger to your preferred style so that your app opens in it's default theme when not running on iOS 13.

Edit: If your users won't be able to change the app's theme on their own from within the app itself then you don't need the light and dark UIColor values in ThemeColor. Just define a defaultColor value and return it at the end of getColor function. This will allow your app to appear in it's default theme for devices running iOS 12 or lower.

like image 167
Ayazmon Avatar answered Nov 08 '22 10:11

Ayazmon