You should not use tag
for identifying views. tag
is very hard to read. The view trait key for it is an internal type, so you'd need to use Mirror
.
You can use the environment instead. Create an environment key for each of the 7+ parameters you will have.
In this case, there are 2 colors, so I'll create 2 keys. If there are more colors, I'd instead use one key that has an array as a value.
struct Color1Key: EnvironmentKey {
static var defaultValue = AnyShapeStyle(.primary)
}
struct Color2Key: EnvironmentKey {
static var defaultValue = AnyShapeStyle(.secondary)
}
extension EnvironmentValues {
var color1: AnyShapeStyle {
get { self[Color1Key.self] }
set { self[Color1Key.self] = newValue }
}
var color2: AnyShapeStyle {
get { self[Color2Key.self] }
set { self[Color2Key.self] = newValue }
}
}
Instead of tag
, write your own view modifiers that read from the environment.
struct Color1Modifier: ViewModifier {
@Environment(\.color1) var color1
func body(content: Content) -> some View {
content.foregroundStyle(color1)
}
}
struct Color2Modifier: ViewModifier {
@Environment(\.color2) var color2
func body(content: Content) -> some View {
content.foregroundStyle(color2)
}
}
extension View {
func color1() -> some View {
modifier(Color1Modifier())
}
func color2() -> some View {
modifier(Color2Modifier())
}
}
// usage:
VStack {
Text(text1).color1()
Text(text2).color2()
}
.modifier(Watermark(style: ...))
Then Watermark
can write to the environment:
func body(content: Content) -> some View {
content
.environment(\.color1, AnyShapeStyle(style == .one ? .red : .black))
.environment(\.color2, AnyShapeStyle(style == .one ? .blue : .pink))
}
Here is an implementation of the same idea but with one environment key holding an array of color styles:
struct CustomView: View {
var text1: String
var text2: String
public var body: some View {
VStack {
Text(text1).color(0)
Text(text2).color(1)
}
.modifier(Watermark(style: ...))
}
}
struct ColorsModifier: ViewModifier {
let index: Int
@Environment(\.colors) var colors
func body(content: Content) -> some View {
content.foregroundStyle(
colors.indices.contains(index) ? colors[index] : AnyShapeStyle(.opacity(1))
)
}
}
extension View {
func color(_ n: Int) -> some View {
modifier(ColorsModifier(index: n))
}
}
struct ColorsKey: EnvironmentKey {
static var defaultValue: [AnyShapeStyle] = []
}
extension EnvironmentValues {
var colors: [AnyShapeStyle] {
get { self[ColorsKey.self] }
set { self[ColorsKey.self] = newValue }
}
}
struct Watermark: ViewModifier {
enum Style {
case one, two
}
var style: Style
func body(content: Content) -> some View {
content
.environment(
\.colors,
style == .one ?
[.init(.red), .init(.blue)] :
[.init(.black), .init(.pink)]
)
}
}