如何让SwiftUI的NavigationLink仅展示当日摄入的食物条目?
问题:如何让卡路里追踪应用仅展示当日摄入的食物列表?
我正在为一款简易卡路里追踪应用添加功能,该应用用于统计全天摄入的卡路里。当前负责展示已摄入食物列表的代码如下:
List { ForEach(food) { food in NavigationLink(destination: EditFoodView(food: food)) { HStack { VStack(alignment: .leading, spacing: 6) { Text(food.name!) .bold() Text("\(Int(food.calories))") + Text(" calories").foregroundColor(.red) } Spacer() Text(calcTimeSince(date: food.date!)) .foregroundColor(.gray) .italic() } } } .onDelete(perform: deleteFood) } .listStyle(.plain)
如您所见,该列表会展示CoreData数据库中存储的所有食物。请问是否有办法让该列表仅展示当日摄入的食物?
解决方案
有两种可行的实现方式,可根据你的数据规模和获取方式选择:
1. 过滤已加载的食物数组
如果你的food是已经从CoreData获取到的内存数组,可以直接在ForEach中添加过滤逻辑,只保留当日记录。
先添加一个判断日期是否为当天的辅助函数:
func isToday(_ date: Date) -> Bool { let calendar = Calendar.current return calendar.isDateInToday(date) }
然后修改ForEach的数据源:
ForEach(food.filter { isToday($0.date!) }) { food in // 原列表项代码保持不变 }
这种方式简单直接,适合数据量较小的场景。
2. 直接从CoreData查询当日数据(推荐)
如果应用中食物数据量较大,过滤内存数组会浪费性能,更高效的方式是在查询CoreData时就限定只获取当日记录。
使用NSPredicate设置日期范围条件:
let calendar = Calendar.current let startOfDay = calendar.startOfDay(for: Date()) // 计算当日结束时间(次日0点) let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)! // 创建查询条件:date >= 当日0点 且 date < 次日0点 let predicate = NSPredicate(format: "date >= %@ AND date < %@", startOfDay as CVarArg, endOfDay as CVarArg) // 将predicate应用到CoreData的获取请求中 let fetchRequest: NSFetchRequest<Food> = Food.fetchRequest() fetchRequest.predicate = predicate // 执行请求获取当日数据
通过这种方式获取的food数组本身就只包含当日记录,直接传入列表即可,无需额外过滤,性能更优。
内容的提问来源于stack exchange,提问作者Ralph L
相关产品推荐
相关产品推荐

