I want to implement a modifier setting for Texts in a similar way as it already exists for Buttons.
Aka:
Button( ... )
.buttonStyle(.plain) // <-- .plain and not PlainStyle()
Problem
Of course I cannot use an opaque which is not really the same. If it would be a View
I could wrap it in an AnyView
but for ViewModifier
s I need another solution.
Error: Function declares an opaque return type,but the return statements in its body do not have matching underlying types
Maybe it is a bonus idea to have something like a .textStyle(.title)
modifier but in my eyes, it could reduce my code to write enormously.
Source
struct TitleStyle: ViewModifier {
func body(content: Content) -> some View {
...
}
}
struct BodyStyle: ViewModifier {
func body(content: Content) -> some View {
...
}
}
enum TextStyle {
case title
case body
// Error: Function declares an opaque return type,
// but the return statements in its body do not have matching underlying types
var modifier: some ViewModifier {
switch self
{
case .title: return TitleStyle()
case .body: return BodyStyle()
}
}
}
It works different way. As all this is around generics we need to restrict declarations for known concrete types.
So, having TitleStyle
and BodyStyle
declared and concrete, we can specify
extension ViewModifier where Self == TitleStyle {
static var title: TitleStyle { TitleStyle() }
}
extension ViewModifier where Self == BodyStyle {
static var body: BodyStyle { BodyStyle() }
}
and then declare extension to use above like
extension View {
func textStyle<Style: ViewModifier>(_ style: Style) -> some View {
ModifiedContent(content: self, modifier: style)
}
}
so as a result we can do as demo
struct Demo_Previews: PreviewProvider {
static var previews: some View {
Text("Demo")
.textStyle(.title)
}
}
Prepared with Xcode 13.4 / iOS 15.5