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

Swift:如何将两个关联实体合并到一个列表并按日期/类型排序?

解决方案

原代码问题分析

你写的代码有几个关键问题:

  1. ForEach无法直接接收两个数组作为数据源,必须先将两个数组合并为一个统一的集合
  2. 直接通过transaction.purchaseArray.name访问属性是错误的——purchaseArray是数组类型,你需要访问数组中单个元素的属性,而非数组本身的属性
  3. 缺少合并后数据的排序逻辑

正确实现步骤

我们可以通过创建一个统一的包装类型,将PurchaseEntity和SellEntity统一处理,再完成合并与排序:

1. 定义统一的交易包装类型

创建枚举来包装两种交易实体,同时提供统一的属性访问方法,方便后续排序和展示:

enum TransactionItem {
    case purchase(PurchaseEntity)
    case sell(SellEntity)
    
    // 统一获取日期(用于排序)
    var date: Date {
        switch self {
        case .purchase(let p): return p.date ?? Date()
        case .sell(let s): return s.date ?? Date()
        }
    }
    
    // 统一获取交易类型
    var type: String {
        switch self {
        case .purchase: return "Purchase"
        case .sell: return "Sell"
        }
    }
    
    // 统一获取名称
    var name: String {
        switch self {
        case .purchase(let p): return p.name ?? ""
        case .sell(let s): return s.name ?? ""
        }
    }
    
    // 统一获取值
    var value: String {
        switch self {
        case .purchase(let p): return p.value ?? ""
        case .sell(let s): return s.value ?? ""
        }
    }
}

2. 在View中合并并排序数据

在你的DetailView中,通过计算属性完成两个数组的合并,以及按日期/类型排序:

struct DetailView: View {
    @StateObject var transaction: TransactionEntity // 注意:这里应该是TransactionEntity而非Transaction
    
    // 合并并排序后的交易列表
    var combinedTransactions: [TransactionItem] {
        // 将两个实体数组转换为统一的TransactionItem类型
        let purchases = transaction.purchaseArray.map { TransactionItem.purchase($0) }
        let sells = transaction.sellArray.map { TransactionItem.sell($0) }
        
        // 合并数组
        let combined = purchases + sells
        
        // 按日期升序排序(如果要按类型排序,替换下方的排序逻辑即可)
        return combined.sorted {
            // 按日期排序:$0.date < $1.date 是升序,反过来是降序
            $0.date < $1.date
            
            // 如果需要按交易类型排序(Purchase在前,Sell在后),使用下面的代码:
            // $0.type < $1.type
        }
    }
    
    var body: some View {
        List(combinedTransactions, id: \.self) { item in
            VStack(alignment: .leading) {
                Text(item.name)
                Text(item.value)
                Text("\(item.date.formatted(date: .abbreviated, time: .omitted)) \(item.type)")
            }
        }
    }
}

3. 额外说明

  • 如果你的Core Data关系属性purchaseArray/sellArray是Set类型(默认生成的关系是Set),需要先转换为数组:Array(transaction.purchaseArray)
  • 日期格式化可以根据需求调整formatted的参数,比如你示例中的01.01.2022格式可以用:
    Text(item.date.formatted(.dateTime.day().month().year()))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:05:27