在我们的应用中,我们有一个基本的调色板用于主要设计,但是用户也有可能通过管理系统选择自己的颜色(用于白色标签目的)。这些颜色作为十六进制字符串返回给我们,并使用以下模型存储在 BusinessProfile
对象中:
struct BusinessProfileColors: Codable {
let success: BusinessProfileColor?
let warning: BusinessProfileColor?
let highlight: BusinessProfileColor?
// ... more colours here
}
struct BusinessProfileColor: Codable {
let light: String?
let dark: String?
}
因此,我正在尝试创建一个类,该类将检查>中是否存在有效的Hex颜色的存在。 BusinessProfile
并使用这些(根据App State选择正确的轻/深色模式颜色)。如果特定调色板的颜色值为 nil
或不是有效的十六进制字符串,我们将落在标准设计颜色上。这是班级的外观:
class ColorPalette: ObservableObject {
@Environment(\.colorScheme) var colorScheme
let container: DIContainer
init(container: DIContainer) {
self.container = container
}
private func dynamicColor(lightColor: Color?, darkColor: Color?, defaultColor: Color) -> Color {
switch colorScheme {
case .dark:
return darkColor ?? lightColor ?? defaultColor
default:
return lightColor ?? defaultColor
}
}
var alertSuccess: Color {
return dynamicColor(
lightColor: Color(hex: container.appState.value.businessData.businessProfile?.colors?.success?.light),
darkColor: Color(hex: container.appState.value.businessData.businessProfile?.colors?.success?.dark),
defaultColor: Color("Success"))
}
// More colours follow the same pattern
}
想法是,我想将其作为 @environmentObject
这样的视图将其传递给我的观点:
@EnvironmentObject var colorPalette: DynamicColors
这样我就可以在这些视图中声明我想要的颜色,例如
text
.foregroundColor(colorPalette.alertSuccess)
:我在我的第一个父视图( rootview.swift
)中声明此类的实例为 @StateObject var
如下:
@StateObject var colorpalette:dynamicColors
因此,当我首次初始化rootview时,它就是这样:(
RootView(viewModel: RootViewModel(container: viewModel.environment.container), colorPalette: .init(container: viewModel.environment.container))
nb: viewModel.environemnt.container
是我们存储 business> businessProfile
)。
然后,我将其作为环境对象从rootview到我需要这样的颜色的第一个视图:
TabBarView(viewModel: .init(container: viewModel.container))
.environmentObject(colorPalette)
但是,在 tabbarview
中,api结果的颜色正在返回和显示,光/暗模式开关无济于事。仅显示光模式颜色。
如果我更改设置,以便在每个视图上单独声明 colorpalette
,然后从这里传递 colorscheme
都可以正常工作,例如:
struct SomeView: View {
@Environment(\.colorScheme) var colorScheme
let container: DIContainer
var colorPalette: ColorPalette {
ColorPalette(colorScheme: colorScheme, container: container) // Pass in the color scheme from the current view and use this in the ColorPalette class
}
}
但是,这似乎是非常沉重的手。我宁愿使用 @environmentObject
,因为它似乎非常适合这种情况。但是,我如何利用 @environment(\。colorscheme)
在这种情况下从我的 colorpalette
类中。
In our app, we have a basic colour palette used for the main design, however there is also the possibility for the user to choose their own colours via an admin system (for white labelling purposes). These colours are returned to us as hex strings and stored in a BusinessProfile
object using the following model:
struct BusinessProfileColors: Codable {
let success: BusinessProfileColor?
let warning: BusinessProfileColor?
let highlight: BusinessProfileColor?
// ... more colours here
}
struct BusinessProfileColor: Codable {
let light: String?
let dark: String?
}
So I am trying to create a class which will check for the presence of valid hex colours in the BusinessProfile
and use these (with the correct light/dark mode colours selected according to the app state). If the colour value for a specific palette is nil
or not a valid hex string, we will fall back on the standard design colours. Here is how the class looks:
class ColorPalette: ObservableObject {
@Environment(\.colorScheme) var colorScheme
let container: DIContainer
init(container: DIContainer) {
self.container = container
}
private func dynamicColor(lightColor: Color?, darkColor: Color?, defaultColor: Color) -> Color {
switch colorScheme {
case .dark:
return darkColor ?? lightColor ?? defaultColor
default:
return lightColor ?? defaultColor
}
}
var alertSuccess: Color {
return dynamicColor(
lightColor: Color(hex: container.appState.value.businessData.businessProfile?.colors?.success?.light),
darkColor: Color(hex: container.appState.value.businessData.businessProfile?.colors?.success?.dark),
defaultColor: Color("Success"))
}
// More colours follow the same pattern
}
The idea is that I want to pass this to my views as an @EnvironmentObject
like this:
@EnvironmentObject var colorPalette: DynamicColors
So that within these views I can declare the colours I want simply like e.g.:
text
.foregroundColor(colorPalette.alertSuccess)
So I am declaring an instance of this class in my first parent view (RootView.swift
) as an @StateObject var
as follows:
@StateObject var colorPalette: DynamicColors
So when I first initialise RootView it is like this:
RootView(viewModel: RootViewModel(container: viewModel.environment.container), colorPalette: .init(container: viewModel.environment.container))
(NB: the viewModel.environemnt.container
is where we store the BusinessProfile
).
Then I am passing this as an environment object from the RootView to the first view where I need the colours like this:
TabBarView(viewModel: .init(container: viewModel.container))
.environmentObject(colorPalette)
However, in TabBarView
, whilst the colours from the API results are returning and being displayed, the light/dark mode switch does nothing. Only the light mode colours are showing.
If I change the setup so that I declare the ColorPalette
individually on each view and pass in the colorScheme
from here all works fine, e.g.:
struct SomeView: View {
@Environment(\.colorScheme) var colorScheme
let container: DIContainer
var colorPalette: ColorPalette {
ColorPalette(colorScheme: colorScheme, container: container) // Pass in the color scheme from the current view and use this in the ColorPalette class
}
}
However, this seems extremely heavy handed and I would much rather use @EnvironmentObject
as it seems well suited to this scenario. However, how can I leverage the @Environment(\.colorScheme)
property in this scenario from within my ColorPalette
class?
发布评论