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

SwiftUI使用Core Data实现发票应用金额税额计算与汇总

问题根因

现有代码计算逻辑错误核心有三点:

  • 计算函数内部每次执行都会新建一个空的FacturationCoreData实例,没有接收列表遍历到的当前商品条目作为入参,读取的全是空属性的默认值,计算结果完全不符合预期
  • 缺少全单维度的汇总逻辑,计算和当前遍历行、全量商品数据完全脱钩
  • 保存新商品后没有清空输入框,重复点击保存会生成大量带空值的无效条目
正确实现方案

核心思路是把无参的计算函数改成接收单条FacturationCoreData实例作为入参,所有单条计算都基于传入的真实条目数据取值,同时新增全单汇总计算逻辑,直接遍历@FetchRequest拉取的全量商品做累加。

1. 替换原有错误的计算函数

删掉原来的prixQuantite()、calculeTvaC()两个错误函数,换成和单条条目绑定的计算方法,以及两个全单汇总的计算属性:

// 计算单条商品不含税小计:单价*数量
func calculateExTaxTotal(for item: FacturationCoreData) -> Double {
    let price = Double(item.prix ?? "") ?? 0
    let quantity = Double(item.quantite ?? "") ?? 0
    return price * quantity
}

// 计算单条商品税额
func calculateTaxAmount(for item: FacturationCoreData) -> Double {
    let exTaxTotal = calculateExTaxTotal(for: item)
    let taxRate = Double(item.tva ?? "") ?? 0
    return exTaxTotal * taxRate / 100
}

// 计算单条商品含税总价
func calculateInTaxTotal(for item: FacturationCoreData) -> Double {
    let exTaxTotal = calculateExTaxTotal(for: item)
    let taxAmount = calculateTaxAmount(for: item)
    return exTaxTotal + taxAmount
}

// 全单总税额汇总
var totalOrderTax: Double {
    factures.reduce(0) { $0 + calculateTaxAmount(for: $1) }
}

// 全单含税总金额汇总
var totalOrderInTax: Double {
    factures.reduce(0) { $0 + calculateInTaxTotal(for: $1) }
}

2. 修复列表行的计算调用

原来列表里调用计算函数时没有传入当前遍历到的facture参数,改成传入对应条目,同时补上要求展示的单条税额字段,金额做两位小数格式化避免显示异常:

List{
    ForEach(factures) { facture in
        VStack(alignment: .leading, spacing: 4){
            Text("商品名: \(facture.article ?? "")")
            Text("数量: \(facture.quantite ?? "")x")
            Text("单价: \(facture.prix ?? "")€")
            Text("税率: \(facture.tva ?? "")%")
            Text("单条不含税小计: \(String(format: "%.2f", calculateExTaxTotal(for: facture)))€")
            Text("单条税额: \(String(format: "%.2f", calculateTaxAmount(for: facture)))€")
            Text("单条含税总价: \(String(format: "%.2f", calculateInTaxTotal(for: facture)))€")
        }.onTapGesture {
            textChange = facture.article ?? ""
        }
    }.onDelete { indexSet in
        indexSet.forEach { index in
            let deletfacture = factures[index]
            viewContext.delete(deletfacture)
            do{
                try viewContext.save()
            }catch{
                print(error)
            }
        }
    }
}

3. 补全全单汇总展示、修复保存逻辑

修改原有保存按钮逻辑,保存成功后清空输入框避免重复提交无效数据,在页面底部新增全单汇总的独立文本展示:

// 修复后的保存按钮逻辑
Button {
    let facture = FacturationCoreData(context: viewContext)
    facture.article = article
    facture.quantite = quantite
    facture.prix = prix
    facture.tva = tvac
    do{
        try viewContext.save()
        // 保存成功清空输入框
        article = ""
        quantite = ""
        prix = ""
        tvac = ""
    }catch{
        print(error)
    }
} label: {
    Image(systemName: "square.and.arrow.down.fill")
        .font(.title)
}

// 在表单底部新增全单汇总区块
Section("全单汇总") {
    Text("全单总税额: \(String(format: "%.2f", totalOrderTax))€")
        .font(.headline)
    Text("全单含税总金额: \(String(format: "%.2f", totalOrderInTax))€")
        .font(.headline)
}
可选优化建议
  • 目前Core Data里把价格、数量、税率都存为String类型,计算时频繁转Double容易出现转换异常,建议直接在Core Data模型编辑器里把这三个属性改成Double类型,在输入环节做格式校验,能减少大量空值转换的冗余代码
  • 税率输入可以直接复用你已经定义好的tva税率数组做Picker选择,不用用户手动输入,能大幅降低填错税率的概率
  • 可以加输入校验,商品名、单价、数量、税率为空时禁用保存按钮,避免生成无效数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:10:01