使用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
相关产品推荐
相关产品推荐

