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

使用NSPredicate BETWEEN查询日期触发NSInvalidArgumentException问题

用NSPredicate的BETWEEN关键字筛选日期范围的正确姿势

嘿,我来帮你搞定这个困扰你的NSPredicate问题!先理清楚来龙去脉,再给你靠谱的解决方案。

你的问题场景

你想通过BETWEEN关键字筛选CoreData实体中e_date属性在指定日期区间的数据,写了代码却触发了NSInvalidArgumentException,提示无法解析格式字符串。你尝试把Swift的Date转成NSDate、把数组转成NSArray都没解决,直到执行了Clean Build Folder操作后错误才消失。

正确的写法其实你一开始就写对了!

你最初的这段代码逻辑完全没问题:

let sd = DateComponents(calendar: Calendar.current,year: 2019, month: 1, day: 1).date!
let ed = DateComponents(calendar: Calendar.current,year: 2020, month: 1, day: 1).date!
let whenPredicate = NSPredicate(format: "e_date BETWEEN %@", [sd, ed])

BETWEEN关键字对应的参数确实需要是一个包含起始和结束值的数组,Swift的数组会自动桥接到Objective-C的NSArray,所以这段代码本身是合法的。

那为什么会报错?大概率是Xcode的缓存搞的鬼!有时候Xcode的编译缓存、索引文件会因为代码变更、版本迭代出现损坏,导致一些莫名其妙的运行时错误,这时候Clean Build Folder就能解决问题——它会清除所有缓存文件,强制Xcode重新构建项目,自然就消除了缓存导致的异常。

额外的两种等价写法

如果你想换种写法,或者担心类似缓存问题,这两种方式也能实现同样的效果:

  • 显式声明NSArray(更明确,避免桥接时的潜在问题):
let dateRange = [sd, ed] as NSArray
let whenPredicate = NSPredicate(format: "e_date BETWEEN %@", dateRange)
  • 用复合谓词替代BETWEEN(逻辑完全等价,适合需要拆分条件的场景):
let startPredicate = NSPredicate(format: "e_date >= %@", sd)
let endPredicate = NSPredicate(format: "e_date <= %@", ed)
let whenPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [startPredicate, endPredicate])

内容的提问来源于stack exchange,提问作者Blazej SLEBODA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:32:38