- A flexible and extensible theming facility to the entire app
- A clean theming code
- A clear boundary between the look and the logic
- Compatibility with pre-iOS 13 devices
By integrating Themer into your app and configuring. Here're the steps:
- Instantiate the theme manager singleton, an instance of the
Themer
class. - Configure it with your app themes.
- For each themable visual element, add a theme-handling method(s) and register it with Themer.
- Whenever needed, toggle the current theme using Themer's
theme
property.
-
First, declare a model for your theme settings, which will represent a collection of the available theme attributes in your app, like in the example below.
import Themer ... struct MyThemeSettings: ThemeModelProtocol { let appBgColor: UIColor let textColor: UIColor }
-
Define your themes (theme settings instances).
extension MyThemeSettings { static let lightTheme = MyThemeSettings( appBgColor: .white, textColor: .black ) static let darkTheme = MyThemeSettings( appBgColor: .gray, textColor: .white ) }
Here, the extension serves for better code organizing.
-
Declare your app's theme enum, which is the key in configuring and using the theme manager.
import Themer ... enum MyTheme: ThemeProtocol { case light case dark var settings: MyThemeSettings { switch self { case .light: return MyThemeSettings.lightTheme case .dark: return MyThemeSettings.darkTheme } } }
Here, the enum's cases behave like “tags” to refer to the available themes. The computed property
settings
maps the enum's cases to their respective theme instances. -
To integrate the theme manager, in your app define the theme manager's singleton, as shown below.
import Themer ... extension Themer where Theme == MyTheme { private static var instance: Themer? static var shared: Themer { if instance == nil { instance = Themer(defaultTheme: .light) } return instance! } }
Notice how the theme manager is configured with the enum
MyTheme
(via theTheme
generic parameter constraining with thewhere
clause) , defined in step 3. -
Define theme-handling method(s) for each themable visual element, like below for a hypothetical
ThemableViewController
, like in the example below.extension ThemableViewController { /// Handles Themer's theme toggle notifications. /// /// - Parameter theme: The new theme. private func handleTheme(_ theme: MyTheme) { view.backgroundColor = theme.settings.appBgColor ... } }
The
handleTheme(_:)
method is where you put all theme configuring code forThemableViewController
. The theme-handler methods can be named arbitrarily. Specific theme attributes can be reached by referring to thesettings
property, which provides access to them. -
Now, by using Themer's method
register(target:action:)
registerThemableViewController
's theme-handling method(s), like in the example below.import Themer ... class ThemableViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Subscribe to theme notifications. Themer.shared.register(target: self, action: ThemableViewController.handleTheme) } }
Note: you should register theme-handling method(s) in the point where their targets (i.e., the visual elements) are ready for immediate theming, as the initial theme applying (with the default theme) is performed at that very moment!
-
Whenever you need to toggle the current theme, you just write, as shown below.
import Themer ... Themer.shared.theme = .dark
- Go to "File" -> "Swift Packages" -> "Add Package Dependency"
- Paste Themer repository URL into the search field:
https://github.com/SerhiyButz/Themer.git
-
Click "Next"
-
Ensure that the "Rules" field is set to something like this: "Version: Up To Next Major: 1.1.0"
-
Click "Next" to finish
For more info, check out here.
Simply Copy and Paste Source/Themer
files in your Xcode Project.
This project is licensed under the MIT license.