如何在SwiftData与SwiftUI中用#Predicate宏过滤数组对象
如何用SwiftData的#Predicate过滤获取当天的DayLog记录?
问题场景
使用Xcode 15 Beta + iOS 17 Beta开发SwiftData+SwiftUI项目,已定义DayLog模型包含createdDate字段,需要过滤出当天的DayLog记录,不清楚如何通过#Predicate实现。
相关代码:
// HomeScreen视图部分代码 import SwiftUI import SwiftData struct HomeScreen: View { @Environment(\.modelContext) private var modelContext @Query private var dayLogs: [DayLog] var todayLog: DayLog { #Predicate({}) var DayLog // 此处需要实现过滤逻辑 } ... }
// DayLog模型定义 @Model final class DayLog: Identifiable { let id = UUID() var createdDate: Date var note: String = "" }
解决方案
方案1:直接在@Query中用#Predicate过滤(推荐)
在数据库层面完成过滤,性能更优,直接获取当天的记录集合:
struct HomeScreen: View { @Environment(\.modelContext) private var modelContext // 通过#Predicate直接查询当天的DayLog @Query(filter: #Predicate<DayLog> { log in let calendar = Calendar.current return calendar.isDate(log.createdDate, inSameDayAs: Date()) }) private var todayLogs: [DayLog] // 获取当天的单条记录(假设每天仅一条) var todayLog: DayLog? { todayLogs.first } // ... 其他视图代码 }
方案2:从已查询的数组中过滤
如果需要基于已有的dayLogs数组做过滤,可直接使用数组的first(where:)方法结合日期判断:
struct HomeScreen: View { @Environment(\.modelContext) private var modelContext @Query private var dayLogs: [DayLog] var todayLog: DayLog? { let calendar = Calendar.current return dayLogs.first(where: { calendar.isDate($0.createdDate, inSameDayAs: Date()) }) } // ... 其他视图代码 }
关键说明
Calendar.isDate(_:inSameDayAs:)是判断日期是否在同一天的简洁方法,无需手动计算当天的起始/结束时间区间。- 如果需要更精确的区间控制(比如严格匹配00:00到次日00:00),可以手动计算时间范围:
let todayStart = calendar.startOfDay(for: Date()) let todayEnd = calendar.date(byAdding: .day, value: 1, to: todayStart)! return log.createdDate >= todayStart && log.createdDate < todayEnd
内容的提问来源于stack exchange,提问作者Kathiresan Murugan
相关产品推荐
相关产品推荐

