首页 > 解决方案 > 从枚举创建列表

问题描述

我希望能够List从一个enum符合CaseIterableCustomStringConvertible例如

public enum HairColor: Int, Codable, CaseIterable, CustomStringConvertible {
    public var description: String {
        switch self {
        case .black:
            return "Black"
        case .blond:
            return "Blond"
        case .brown:
            return "Brown"
        case .red:
            return "Red"
        case .grey:
            return "Gray"
        case .bald:
            return "Bald"
        }
    }
    case blond, brown, black, red, grey, bald
}
struct ContentView: View {
    var body: some View {
        SwiftUIHelpers.enumToList(HairColor)
    }
}

这是我尝试过的方法,但出现错误:“无法将'Text'类型的值转换为闭包结果类型'_”


struct SwiftUIHelpers {
    static func enumToList<T: CaseIterable, RandomAccessCollection>(_ a: T) -> some View {
        List {
            ForEach(a, id: \.rawValue) { (o: CustomStringConvertible) in
                Text(o.description)
            }
        }
    }
}

我的方式有什么错误?!?

标签: swiftui

解决方案


这是工作解决方案。使用 Xcode 11.4 / iOS 13.4 测试。

struct SwiftUIHelpers {
    static func enumToList<T: CaseIterable>(_ t: T.Type) -> some View 
           where T.AllCases: RandomAccessCollection, T: Hashable & CustomStringConvertible {
        List {
            ForEach(t.self.allCases, id: \.self) { o in
                Text(o.description)
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        SwiftUIHelpers.enumToList(HairColor.self)
    }
}

public enum HairColor: Int, Codable, Hashable, CaseIterable, CustomStringConvertible {
    public var description: String {
        switch self {
        case .black:
            return "Black"
        case .blond:
            return "Blond"
        case .brown:
            return "Brown"
        case .red:
            return "Red"
        case .grey:
            return "Gray"
        case .bald:
            return "Bald"
        }
    }
    case blond, brown, black, red, grey, bald
}

更新:玩了这个之后,我发现以下扩展可能会更有帮助

extension CaseIterable where Self.AllCases: RandomAccessCollection, Self: Hashable & CustomStringConvertible {
    static func toForEach() -> some View  {
        ForEach(Self.allCases, id: \.self) { o in
            Text(o.description).tag(o)
        }
    }
}

因为提供了更广泛的重用可能性,例如

List { HairColor.toForEach() }

和这个

Form { HairColor.toForEach() }

演示

struct DemoHairColorPicker: View {
    @State private var hairColor: HairColor = .red
    var body: some View {
        VStack {
            Text("Selected: \(hairColor.description)")
            Picker(selection: $hairColor, label: Text("Hair")) { HairColor.toForEach() }
        }
    }
}

当然在任何堆栈中VStack { HairColor.toForEach() }


推荐阅读