You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何在List中同时传入多个CaseIterable枚举数据源?

SwiftUI中同时展示三个CaseIterable枚举的对应内容

问题场景

你有三个实现了CaseIterable协议的枚举,希望在SwiftUI的List中同时展示三个枚举的对应项(名称、编码、数值),但目前只能单独传入一个枚举的数据源。由于枚举案例多达20个,不想手动逐个创建结构体实例(避免重复劳动),同时要保留枚举带来的类型安全、减少拼写错误的优势。

当前单独使用一个枚举的代码

VStack {
    List(OtherWoundsName.allCases, id: \.self) { name in
        Text(name.rawValue)
    }
}

原手动创建结构体的方式(不希望使用)

struct BillingData {
    let name: String
    let code: String
    let value: String
}

var allOtherWounds = [
    BillingData(name: OtherWoundsName.secondaryclosure_name.rawValue, code: OtherWoundsCode.secondaryclosure_code.rawValue, value: OtherWoundsValue.secondaryclosure_value.rawValue),
    BillingData(name: OtherWoundsName.musclerepair_name.rawValue, code: OtherWoundsCode.musclerepair_code.rawValue, value: OtherWoundsValue.musclerepair_value.rawValue),
    BillingData(name: OtherWoundsName.woundone_name.rawValue, code: OtherWoundsCode.woundone_code.rawValue, value: OtherWoundsValue.woundone_value.rawValue)
]

期望的理想写法

VStack {
    List(OtherWoundsName.allCases, OtherWoundsCode.allCases, OtherWoundsValue.allCases, id: \.self) { name, code, value in
        Text(name.rawValue)      
        Text(code.rawValue)
        Text(value.rawValue)
    }
}

可行实现方案

核心思路是利用Swift的序列合并能力,在保证三个枚举案例数量一致、顺序严格对应的前提下,将三个枚举的allCases序列合并,直接在List中使用合并后的序列,既保留类型安全,又无需手动创建结构体实例。

前提条件

确保三个枚举的案例顺序完全匹配,每个位置的案例对应同一业务项:

// 名称枚举
enum OtherWoundsName: String, CaseIterable {
    case secondaryclosure_name = "二期缝合"
    case musclerepair_name = "肌肉修复"
    case woundone_name = "伤口1"
    // 其余20个案例...
}

// 编码枚举(顺序与名称枚举完全对应)
enum OtherWoundsCode: String, CaseIterable {
    case secondaryclosure_code = "CODE001"
    case musclerepair_code = "CODE002"
    case woundone_code = "CODE003"
    // 其余20个案例...
}

// 数值枚举(顺序与前两个枚举完全对应)
enum OtherWoundsValue: String, CaseIterable {
    case secondaryclosure_value = "100"
    case musclerepair_value = "200"
    case woundone_value = "300"
    // 其余20个案例...
}

方案1:使用嵌套zip合并序列(无需额外代码)

Swift标准库的zip函数可以合并两个序列,嵌套使用即可合并三个序列:

VStack {
    List(zip(zip(OtherWoundsName.allCases, OtherWoundsCode.allCases), OtherWoundsValue.allCases), id: \.0.0) { ((name, code), value) in
        VStack(alignment: .leading) {
            Text(name.rawValue)
            Text(code.rawValue).foregroundColor(.gray)
            Text(value.rawValue).foregroundColor(.blue)
        }
    }
}
  • zip(zip(a,b),c)会将三个序列按索引配对,生成包含三个枚举案例的嵌套元组
  • id: \.0.0使用第一个枚举案例作为唯一标识,保证List的稳定性

方案2:自定义zip3函数(更接近理想写法)

如果觉得嵌套zip可读性差,可以自定义一个支持合并三个序列的zip3函数:

// 自定义合并三个序列的工具函数
func zip3<A, B, C>(_ a: A, _ b: B, _ c: C) -> Zip3Sequence<A, B, C> where A: Sequence, B: Sequence, C: Sequence {
    Zip3Sequence(a, b, c)
}

struct Zip3Sequence<A: Sequence, B: Sequence, C: Sequence>: Sequence {
    typealias Element = (A.Element, B.Element, C.Element)
    
    private let a: A
    private let b: B
    private let c: C
    
    init(_ a: A, _ b: B, _ c: C) {
        self.a = a
        self.b = b
        self.c = c
    }
    
    func makeIterator() -> Iterator {
        Iterator(a.makeIterator(), b.makeIterator(), c.makeIterator())
    }
    
    struct Iterator: IteratorProtocol {
        private var aIterator: A.Iterator
        private var bIterator: B.Iterator
        private var cIterator: C.Iterator
        
        init(_ a: A.Iterator, _ b: B.Iterator, _ c: C.Iterator) {
            self.aIterator = a
            self.bIterator = b
            self.cIterator = c
        }
        
        mutating func next() -> Element? {
            guard let a = aIterator.next(), let b = bIterator.next(), let c = cIterator.next() else {
                return nil
            }
            return (a, b, c)
        }
    }
}

之后就可以用接近你理想的写法实现List:

VStack {
    List(zip3(OtherWoundsName.allCases, OtherWoundsCode.allCases, OtherWoundsValue.allCases), id: \.0) { name, code, value in
        VStack(alignment: .leading) {
            Text(name.rawValue)
            Text(code.rawValue).foregroundColor(.gray)
            Text(value.rawValue).foregroundColor(.blue)
        }
    }
}

注意事项

  • 必须保证三个枚举的案例数量完全一致,否则zip会以最短的序列为准,多余的案例会被忽略
  • 案例顺序必须严格对应,否则会出现数据匹配错误
  • 两种方案都保留了枚举的类型安全特性,避免手动输入rawValue带来的拼写错误

内容的提问来源于stack exchange,提问作者Amar Cheema

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:33:34