0

I'm rendering some views that have a dynamic list of modifiers:

public enum Colors:String, CaseIterable {
    public func to_color() -> Color {
        color_hex(self.rawValue)
    }
    
    case black          = "#000000"
    case white          = "#FFFFFF"
    case gray_500       = "#F9FAFB"
    case blue_200       = "#BFDBFE"
    case blue_500       = "#3B82F6"
}

public enum Style {
    case bg(Colors)
    case text(Colors)
}


struct StyleModifier: ViewModifier {
    fileprivate let properties: [Style]

    func body(content: _ViewModifier_Content<StyleModifier>) -> some View {
        return apply(content: content.toAnyView(), properties)
    }
}

public extension View {
    func toAnyView() -> AnyView {
        return AnyView(self)
    }

    func style(_ clsName: [Style]) -> some View {
        ModifiedContent(content: self, modifier: StyleModifier(properties: clsName))
    }

    func style2(_ clsName: [Style]) -> some View {
        ModifiedContent(content: self, modifier: StyleModifier2(properties: clsName))
    }
}

... and try to make this without resorting to AnyView but nothings get applied.

My working code with AnyView:

func apply(content: AnyView, _ properties: [Style]) -> AnyView {
    return properties.reduce(content) { (v: AnyView, style: Style) -> AnyView in
        switch style {
        case .bg(let color):
            return v.background(color.to_color()).toAnyView()
        case .text(let color):
            return v.foregroundColor(color.to_color()).toAnyView()
    }
}

I try to translate this with generics:

func apply2<V: View>(of: V, _ properties: [Style]) -> V {
    return properties.reduce(of) { (v: V, style: Style) -> V in
        switch style {
        case .bg(let color):
            return v.background(color.to_color()) as! V
        case .text(let color):
            return v.foregroundColor(color.to_color()) as! V
    }
}

But then this not work. Why?

mamcx
  • 15,916
  • 26
  • 101
  • 189
  • Why? Because `background` and `foregroundColor` does not return the same type. It's not `V` anymore after you apply the modifier. – Sweeper May 12 '22 at 21:00
  • Ok, I was surprised this not cause a error then. Is possible to make this work or using AnyView is the only way? – mamcx May 12 '22 at 21:28
  • Beware of the performance implications of AnyView. Watch Demystifying Swift from WWDC 2021 for more info. – jnpdx May 13 '22 at 04:50
  • Maybe [this post](https://stackoverflow.com/questions/65401146/add-view-as-a-parameter-to-a-custom-viewmodifier) is helpful. It passes the view to a ViewModifier instead. – LoVo May 13 '22 at 05:49
  • Yeah, I think the problem is the fact I get a list of "styles" and can't code it directly on swift, instead I need to interpret them. – mamcx May 13 '22 at 17:03

0 Answers0