SwiftUI列表与上条日期相同不显示,UserDefaults存值失效如何解决
问题根因
你的现有逻辑有3个明显问题:
- UserDefaults键名不匹配:读取时用的key是
storeDate,写入时用的key是saveDate,两者完全不一致,导致写入的值永远读不出来。 - 首次赋值逻辑缺失:当
savedDate为空(也就是第一条数据)时,你仅设置了输出的日期,没有把当前日期赋值给savedDate,导致写入UserDefaults的仍然是空值,后续所有判断都会失效。 - 临时状态不该持久化存储:用来对比的上一条日期只是列表渲染时的临时状态,列表刷新、条目增删、排序变化时都需要重置,存在UserDefaults这种持久化存储里会导致后续进入页面逻辑全部错乱。
方案1:快速修复现有逻辑
完全不需要用UserDefaults,直接在UserData里加一个临时属性存上一次渲染的日期即可:
- 先在
UserData类中新增属性:
// 存储列表渲染时上一条的日期,每次列表刷新要重置 var lastRenderedDate: String = ""
- 重写
ckEntryDate方法:
func ckEntryDate(item: CurrTrans) -> String { let currDate = (item.entryDT ?? Date()).getFormattedDate() // 和上一条日期相同就返回空 guard currDate != lastRenderedDate else { return "" } // 不同就更新缓存,返回当前日期 lastRenderedDate = currDate return currDate }
- 在
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:更合理的标准实现(推荐)
这种按日期分组展示的列表,直接用系统的分组逻辑即可,不需要自己维护前后条目对比的状态,逻辑更稳定:
- 先在
HistoryView里新增计算属性,把Core Data的查询结果按日期分组:
// 按日期分组的交易数据 var groupedTrans: [String: [CurrTrans]] { Dictionary(grouping: currTrans) { item in (item.entryDT ?? Date()).getFormattedDate() } } // 排序后的日期数组,按自己需要调整正序/倒序 var sortedDates: [String] { groupedTrans.keys.sorted(by: >) }
- 改造列表渲染逻辑,用
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
相关产品推荐
相关产品推荐

