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

SwiftUI列表与上条日期相同不显示,UserDefaults存值失效如何解决

问题根因

你的现有逻辑有3个明显问题:

  1. UserDefaults键名不匹配:读取时用的key是storeDate,写入时用的key是saveDate,两者完全不一致,导致写入的值永远读不出来。
  2. 首次赋值逻辑缺失:当savedDate为空(也就是第一条数据)时,你仅设置了输出的日期,没有把当前日期赋值给savedDate,导致写入UserDefaults的仍然是空值,后续所有判断都会失效。
  3. 临时状态不该持久化存储:用来对比的上一条日期只是列表渲染时的临时状态,列表刷新、条目增删、排序变化时都需要重置,存在UserDefaults这种持久化存储里会导致后续进入页面逻辑全部错乱。

方案1:快速修复现有逻辑

完全不需要用UserDefaults,直接在UserData里加一个临时属性存上一次渲染的日期即可:

  1. 先在UserData类中新增属性:
// 存储列表渲染时上一条的日期,每次列表刷新要重置
var lastRenderedDate: String = ""
  1. 重写ckEntryDate方法:
func ckEntryDate(item: CurrTrans) -> String {
    let currDate = (item.entryDT ?? Date()).getFormattedDate()
    // 和上一条日期相同就返回空
    guard currDate != lastRenderedDate else { return "" }
    // 不同就更新缓存,返回当前日期
    lastRenderedDate = currDate
    return currDate
}
  1. 在HistoryView的列表每次出现时重置缓存,避免增删条目后逻辑出错:
List {
    ForEach(currTrans, id: \.id) { item in
        let entryDate = userData.ckEntryDate(item: item)
        showRow(g:g, item: item, entryDate: entryDate)
    }
    .onDelete(perform: deleteItem)
}
.onAppear {
    // 每次列表刷新前重置日期缓存
    userData.lastRenderedDate = ""
}

方案2:更合理的标准实现(推荐)

这种按日期分组展示的列表,直接用系统的分组逻辑即可,不需要自己维护前后条目对比的状态,逻辑更稳定:

  1. 先在HistoryView里新增计算属性,把Core Data的查询结果按日期分组:
// 按日期分组的交易数据
var groupedTrans: [String: [CurrTrans]] {
    Dictionary(grouping: currTrans) { item in
        (item.entryDT ?? Date()).getFormattedDate()
    }
}
// 排序后的日期数组,按自己需要调整正序/倒序
var sortedDates: [String] {
    groupedTrans.keys.sorted(by: >)
}
  1. 改造列表渲染逻辑,用Section做分组头显示日期:
List {
    ForEach(sortedDates, id: \.self) { date in
        Section(header: Text(date)) {
            ForEach(groupedTrans[date] ?? [], id: \.id) { item in
                showRow(g: g, item: item, entryDate: "")
            }
        }
    }
    .onDelete(perform: deleteItem)
}

附加优化

你现在的Date扩展每次调用都会新建DateFormatter,开销很大,建议改成静态单例:

extension Date {
    private static let sharedDateFormatter: DateFormatter = {
        let fmt = DateFormatter()
        fmt.dateStyle = .medium
        fmt.timeStyle = .none
        return fmt
    }()
    
    func getFormattedDate() -> String {
        Self.sharedDateFormatter.string(from: self)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:15:00