SwiftTheme: a runtime theme and skin manager for iOS and tvOS apps
🎨 Powerful theme/skin manager for iOS 9+ 主题/换肤, 暗色模式
At a glance
- What is it?
- SwiftTheme handles day/night switching in UIKit apps through two modes, an index-based picker for a fixed set of themes and a plist/JSON mode for downloadable skin packages. It is a small, MIT-licensed Swift library, and the interesting question is whether its runtime approach still fits an app you are starting in 2026.
- Who is it for?
- Adopt SwiftTheme if you maintain a UIKit codebase, need more than two skins, and want to ship plist-driven theme packages without rewriting view controllers. Do not adopt it if your app is SwiftUI-first, or if you only need the system dark mode that iOS already provides, since the library is a UIKit runtime layer and adds a dependency you would not otherwise carry.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 136 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem SwiftTheme was built to remove
The README opens with the origin story rather than a feature list, and it is worth reading as a design brief. The author needed a night mode and concluded that changing brightness or alpha on a top-level view was not enough: a real theme switch means different colors, different alpha values and different image cuts. The naive implementation, a global variable read during controller initialization plus notifications to update views that already exist, produces controllers full of notification registration, unregistration, if/else branches and UI update code. The README also names the failure mode of that approach directly: if you forget to unregister a notification, the app may crash.
So the target user is an iOS or tvOS developer with a UIKit codebase and a theming requirement that goes beyond a single boolean. The library is for teams that want to attach theme-aware values to views without scattering switch statements through their controllers. It is not a design system and it does not ship themes; it is the plumbing that maps a selected theme to the properties of live views.
Index mode and plist mode: two ways to bind a value to a view
SwiftTheme exposes parallel properties on UIKit views, all prefixed with theme_, so theme_backgroundColor corresponds to backgroundColor and theme_image to image. The two modes differ in what you assign to those properties.
In index mode you assign a literal array of values, one per theme, and the position in the array is the theme index. The README shows a view whose background color is set to ["#FFF", "#000"], a label or button whose text color is set to ["#000", "#FFF"], and an image view whose image is set to ["day", "night"]. Switching is a single call to ThemeManager.setTheme(index:), and ThemeManager.currentThemeIndex is a read-only property that reports the active index. The README describes index mode as the fast route for the case of a few themes and no need to download more.
Plist mode replaces the array with a key path into a plist file. The README example assigns "Global.backgroundColor" to theme_backgroundColor and "SelectedThemeCell.iconImage" to theme_image. The plist plus its resource files form a theme package, and the switching call takes the plist name and a path, for example ThemeManager.setTheme(plistName: "Red", path: .mainBundle). Because the values live in a file rather than in compiled code, plist mode is what lets an app download and install themes later without changing logic code.
One detail in the README is easy to miss and will cost you a compile error. Assigning a stored array variable to a theme property does not work, because the property accepts a ThemeColorPicker, not an Array. The literal form works because it initializes a picker through Swift's literal conversion. The README calls this out with a wrong example and two correct forms, including an explicitly typed let colorPickers: ThemeColorPicker = ["#FFF", "#000"].
Installing SwiftTheme and setting a first theme
The README lists four installation routes: CocoaPods, Carthage, Swift Package Manager, and copying the files in the Sources folder into your project. The repository also contains a Package.swift, so the Swift Package Manager path is present in the source tree, not just in prose. For CocoaPods the README gives the pod line and the use_frameworks! directive, and for Carthage it gives the GitHub line with the owner and repository name.
pod 'SwiftTheme'
use_frameworks!github "wxxsw/SwiftTheme"For Swift Package Manager the README describes the Xcode flow rather than a Package.swift snippet: choose File, then Swift Packages, then Add Package Dependency, and enter the repository URL. If you prefer editing files, the Package.swift at the repository root is the artifact to point at.
A first working setup is small. Pick two colors, assign them to a view, then switch. The README's own demo does exactly this with a night flag.
view.theme_backgroundColor = ["#FFF", "#000"]
label.theme_textColor = ["#000", "#FFF"]
ThemeManager.setTheme(index: isNight ? 1 : 0)After the setTheme call the views that were assigned pickers should repaint to the value at the given index. The README notes that index 0 is "#FFF" and index 1 is "#000" in its example, so the index and the array position must stay in sync across every assignment in your codebase. That is the main maintenance cost of index mode: adding a third theme means revisiting every theme_ assignment and extending every array.
If you want to see the library running before integrating it, the README points at the workspace: open SwiftTheme.xcworkspace and run the PlistDemo target. The repository also contains JsonDemo, OCDemo and TVOSDemo targets, and the README states that the library is fully compatible with Objective-C, with a pickerWithColors: example.
Where the runtime approach bites back
The library is described as based on runtime, and that is the source of both its convenience and its limits. Theme properties are attached to UIKit classes, so the mechanism depends on Objective-C runtime behavior and on the view hierarchy being reachable when a theme is applied.
The README does not document what happens to a view that is not yet in a hierarchy, or a controller that is off screen, when setTheme is called. It also does not document rollback, partial application, or a verification step that confirms every picker resolved successfully. That silence matters in practice: a theme switch that runs while a table view is recycling cells is exactly the scenario the library was written for, and the README gives no statement about ordering or timing guarantees. Treat the switch as a state change you must test against your own screens rather than something the README promises.
The literal-versus-variable rule is a second sharp edge. Because the properties take picker types, code that looks reasonable, storing colors in a let and assigning the variable, fails at compile time. The README documents this, but it is the kind of detail that pushes teams toward an explicit typed picker everywhere.
Finally, the deployment range is iOS 9+ and tvOS 9+, which is stated on the badge line and in the platform description. If your project has moved past UIKit, or if your theming needs are satisfied by the system appearance APIs, SwiftTheme is the wrong layer: it solves a UIKit problem, and adopting it in a SwiftUI-first app means carrying a dependency whose extension properties do not apply to your views.
SwiftTheme compared with the system appearance route
The obvious alternative is not another third-party library; it is the platform's own appearance handling, which arrived with iOS 13 and lets an app declare light and dark variants without a theme manager. The difference in approach is structural. System appearance is declarative and tied to the trait environment: you describe two variants, and the framework decides when to apply them. SwiftTheme is imperative and index- or key-driven: you hold a theme index or a plist name, and you call setTheme to push values into views through runtime-attached properties.
That difference decides the choice. If your requirement is exactly two appearances and they map to light and dark, the system route needs no dependency and no index bookkeeping. SwiftTheme earns its place when the requirement is more than two skins, when themes must be swappable at runtime from a downloaded package, or when the app must support iOS versions that predate the system appearance APIs. The plist mode is the part with no direct platform equivalent: shipping a theme as a plist plus resources, and loading it from the main bundle or the sandbox, is a distribution model the system APIs do not provide. The README is explicit that plist mode exists so you can add downloading and installing themes without touching logic code, and that is the strongest argument for this library over the built-in route.
Maintenance, licence and what a fork inherits
The repository is not archived, and the last push was on 2026-05-17. The README describes the library as written in Swift, compatible with Objective-C, and available under the MIT licence, which is the licence file at the repository root. MIT is permissive: it allows commercial and closed-source use, and the obligation it imposes is preserving the copyright notice and permission text. This is not legal advice, and if your organisation has a policy on third-party dependencies, route the LICENSE file through it.
Upgrade cost is dominated by two things. First, the index-mode contract: every theme_ assignment encodes the theme order in an array, so a new theme is a code change in every file that assigns a picker. Plist mode removes that specific cost, which is why the README frames it as the extensible option. Second, the runtime mechanism: a library that attaches properties to UIKit classes is coupled to the frameworks it extends, and you should confirm your toolchain and deployment target against the Swift version and platform range the README states before planning a migration. The repository contains a Podfile.lock and a Travis configuration, which tells you the project has historically been built through CocoaPods and CI, but the README does not describe a release or versioning policy, so pin the version you install rather than tracking the branch.
Editorial conclusion
Adopt SwiftTheme if you maintain a UIKit codebase, need more than two skins, and want to ship plist-driven theme packages without rewriting view controllers. Do not adopt it if your app is SwiftUI-first, or if you only need the system dark mode that iOS already provides, since the library is a UIKit runtime layer and adds a dependency you would not otherwise carry. Before committing, verify that your deployment target still matches the iOS 9+ and tvOS 9+ range stated in the README, check that the Swift Package Manager route resolves against your toolchain, and confirm how your own views behave when ThemeManager.setTheme is called while a controller is off screen.
Frequently asked questions
What is SwiftTheme used for?
It is a theme and skin manager for iOS and tvOS apps, used to switch colors, text colors and images across UIKit views. The README describes it as a reusable framework for night mode and multi-theme apps, with an index mode for a few themes and a plist mode for downloadable theme packages.
How do I install SwiftTheme?
The README lists CocoaPods, Carthage, Swift Package Manager and copying the Sources folder into your project. For CocoaPods the pod line is pod 'SwiftTheme' with use_frameworks!, and for Carthage it is github "wxxsw/SwiftTheme".
Does SwiftTheme work with Objective-C?
The README states that the library is fully compatible with Objective-C and shows a pickerWithColors: example for setting a label's background color. The repository also contains an OCDemo target alongside the Swift demos.
Why does assigning an array variable to theme_backgroundColor fail to compile?
Because the property takes a ThemeColorPicker, not an Array. The README says the literal form ["#FFF", "#000"] works through literal initialization, and that a stored array must instead be declared as a ThemeColorPicker before assignment.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wxxsw-swifttheme)