如何优化swiftui中的switch case

How to optimize switch case in swiftui

我有一个视图可以根据传入的参数显示不同的样式

有50多种不同的风格,每种风格都有冲突的布局。我想根据传入的样式显示不同的样式

我要写50多个案例如下:

struct StyleDefaultView: View {
    let style: Int
    var body: some View {
        VStack() {
            Text("111")
        }
        
    }
}

struct Style1View: View {
    let style: Int
    var body: some View {
        HStack() {
            VStack() {
                Text("111")
            }
            Text("222")
        }
    }
}

struct Style2View: View {
    let style: Int
    var body: some View {
        VStack() {
            Text("111")
            HStack() {
                Text("111")
                Text("111")
            }
        }
        Text("222")
    }
}

struct Style3View: View {
    let style: Int
    var body: some View {
        HStack() {
            Text("111")
            VStack() {
                Text("111")
                Text("111")
            }
        }
        Text("222")
    }
}

struct Style4View: View {
    let style: Int
    var body: some View {
        HStack() {
            Text("222")
            VStack() {
                Text("111")
                Text("111")
            }
            Text("111")
        }
    }
}

// ... other 50+ style

struct ContentView: View {
    let style: Int
    var body: some View {
        VStack() {
            switch style {
            case 1:
                Style1View(style: style)
            case 2:
                Style2View(style: style)
            case 3:
                Style3View(style: style)
            case 4:
                Style4View(style: style)
            // case .. other 50+ style
            default:
                StyleDefaultView(style: style)
            }
        }
    }
}

有没有办法简化这些 swift 案例代码?类似于 Java 中的反射,如下代码

struct ContentView: View {
    let style: Int
    let viewMap = [
        0 : "StyleDefaultView",
        1 : "Style1View",
        2 : "Style2View",
        3 : "Style3View",
        // ... other 50 views
    ]
    var body: some View {
        let viewName: String = viewMap[style] ?? "StyleDefaultView"
        //  initialization a view by a string 
        viewName(style : style)
    }
}

编辑:

这只是一个让您考虑循环不同样式视图的示例:

struct StyleDefaultView: View {
    var body: some View {
        VStack() {
            Text("111")
        }
    }
}

struct Style1View: View {
    var body: some View {
        HStack() {
            VStack() {
                Text("111")
            }
            Text("222")
        }
    }
}

struct Style2View: View {
    var body: some View {
        VStack() {
            Text("111")
            HStack() {
                Text("111")
                Text("111")
            }
        }
        Text("222")
    }
}
struct Style3View: View {
    var body: some View {
        Text("1112")
        Text("1112")
        Text("1112")
    }
}

struct Style4View: View {
    var body: some View {
        Text("1112")
        Text("1")
    }
}

class StyleViewModel {
    let styles: [AnyView] = [
        AnyView(Style1View()),
        AnyView(Style2View()),
        AnyView(Style3View()),
        AnyView(Style4View())]
    
    func selectedStyleView(_ ndx: Int) -> AnyView {
        if ndx < styles.count {
            return styles[ndx]
        } else {
            return AnyView(StyleDefaultView())
        }
    }
}

struct ContentView: View {
    let styles = StyleViewModel()
    let style: Int = 2

    var body: some View {
        styles.selectedStyleView(style)
    }
}

我认为更好的方法是使用每个协议都符合的协议。然后你只需要存储类型,这意味着它真的很轻量级,因为你没有实例化一堆你可能不需要使用的视图。

例子

首先,ContentView 这样您就可以主要了解正在发生的事情。这是一个带有 Slider 的交互式示例,因此您可以更改样式以对其进行测试。

struct ContentView: View {
    private static let styleTypes: [StyledView.Type] = [
        StyleDefaultView.self,
        Style1View.self,
        Style2View.self,
        Style3View.self,
        Style4View.self
    ]

    @State private var currentStyle = 0

    var body: some View {
        VStack {
            Text("Style: \(currentStyle)")

            Slider(
                value: Binding<Double>(
                    get: { Double(currentStyle) },
                    set: { currentStyle = Int([=10=]) }
                ),
                in: 0 ... 4,
                step: 1
            )

            Spacer()

            Self.styleTypes[currentStyle].init().buildView()
        }
    }
}

结果(还有其余代码):

协议:

protocol StyledView {
    init()
    func buildView() -> AnyView
}

extension StyledView where Self: View {
    func buildView() -> AnyView {
        AnyView(self)
    }
}

现在您需要做的就是使每个视图符合 StyledView,无需在每个视图中编写额外的代码。第一视图示例(但对所有视图都执行此操作):

struct StyleDefaultView: View, StyledView {
    var body: some View {
        VStack() {
            Text("111")
        }
    }
}

旁注:VStack 不需要那些 () 因为你有尾随闭包。