Gestalt
Gestalt 是一个 无侵入式 和 轻量级 的框架,用于应用主题化,支持 动态主题切换。
用法
假设您想为一个带有单个标签的视图控制器设置主题
import Gestalt
struct Theme: Gestalt.Theme {
let view: ViewTheme = .init()
static let light: Theme = .init(view: .light)
static let dark: Theme = .init(view: .dark)
}
struct ViewTheme: Gestalt.Theme {
let font = UIFont.preferredFont(forTextStyle: .headline)
let color: UIColor
let backgroundColor: UIColor
static let light: Theme = .init(
color: UIColor.black
backgroundColor: UIColor.white
)
static let dark: Theme = .init(
color: UIColor.white
backgroundColor: UIColor.black
)
}
// In `AppDelegate.application(_:didFinishLaunchingWithOptions:)`
// assign a default theme (or user's choice from user defaults):
ThemeManager.default.theme = Theme.light
class ViewController: UIViewController {
@IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.observe(theme: \Theme.view)
}
}
extension ViewController: Themeable {
typealias Theme = ViewTheme
func apply(theme: Theme) {
self.view.backgroundColor = theme.backgroundColor
self.label.textColor = theme.color
self.label.font = theme.font
}
}
调用 self.observe(theme: \Theme.view)
在 ThemeManager.default
上为未来的主题更改注册观察者,然后立即调用一次。初始调用不是动画的,但是任何后续更改都是动画的。
要更改当前主题(即使在应用运行时)只需将不同的主题分配给当前使用的 ThemeManager
ThemeManager.default.theme = Theme.dark
这将会导致之前在给定 ThemeManager
上注册的所有闭包再次被调用。
查看 GestaltDemo
目标以获取一个更现实/更复杂的用法示例。
注意
- 通常使用
ThemeManager.default
就足够了。然而,也可以通过let manager = ThemeManager()
创建专门的ThemeManager
。
在应用扩展中的应用
在视图已经加载完成之后使用外观代理,这个库使用一种技巧,通过从主窗口中移除并重新添加应用程序的根视图来激活代理。在应用扩展(如图表小工具)中,这是不可能的,因为扩展的安全API限制了对外部主窗口的访问。因此,要在应用扩展中使用此库,您需要手动通过添加以下内容到您根视图控制器中设置主题后触发根视图的重新加载。
ThemeManager.default.observe(theme: Theme.self) { [weak self] _ in
if let strongSelf = self, let superview = strongSelf.view.superview {
strongSelf.view.removeFromSuperview()
superview.addSubview(strongSelf.view)
}
}
重要
func apply(theme: Theme)
的实现应该具有 幂等性,以避免在重复调用时的副作用。
安装
将 Gestalt 添加到项目的推荐方法是使用 Carthage
github 'regexident/Gestalt' ~> 2.0.0
或通过 Cocoapods
pod 'Gestalt', '~> 2.0.0'
let package = Package(
name: "GestaltDemo",
dependencies: [
.package(url: "https://github.com/regexident/Gestalt.git", from: "2.0.0")
],
targets: [
.target(name: "GestaltDemo", dependencies: [ "Gestalt" ])
]
)
许可证
Gestalt 依据 MPL-2.0 许可证 提供。更多信息请参阅 LICENSE
文件。