具有用于比较日期的瞬态属性的 FetchedResultsController

FetchedResultsController with transient attribute for comparing dates

我在 CoreData 中有一个 JOURNEY 实体。它具有 arrivalDate 和 departmentDate 作为属性。

arrivalDate 和 departureDate 都是 NSDate 类型?

我只想获取持续时间超过一个小时的旅程。

为了实现这一点,我在 Journey+CoreDataClass 中创建了一个瞬态属性

public var isJourneyLongEnough: Bool{
    if let arrival = arrivalDate as Date?, let departure = departureDate as Date?{
        let duration = departure.timeIntervalSince(arrival)
        return duration >= 3600 ? true : false
    } else{
        return false
    }
}

当我尝试获取它时崩溃并出现错误:*** 由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'keypath isJourneyLongEnough not found in entity.

在对这个问题进行更多研究后,我发现我们不能在谓词中使用瞬态 属性,因为从 persistentStore 获取托管对象时这些不存在。

You cannot fetch using a predicate based on transient properties (although you can use transient properties to filter in memory yourself). ... To summarize, though, if you execute a fetch directly, you should typically not add Objective-C-based predicates or sort descriptors to the fetch request. Instead you should apply these to the results of the fetch.

实现此目标的最佳方法是什么?我正在使用 FetchedResultsController 在 UITableView

中显示所有旅程

您可以试试下面的 NSPredicate,它基于 another question,本质上是将日期转换为 NSNumber,减去它们,然后比较结果是大于还是小于 3600 秒。

我没试过,但也许有帮助。最初的问题是在 ObjC 中,所以也许有些事情发生了变化。

NSPredicate(format: “departureDate != nil AND arrivalDate != nil AND CAST(departureDate, ‘NSNumber‘) - CAST(arrivalDate, ‘NSNumber‘) >= 3600“)

时间戳以秒为单位存储(自参考日期 2001 年 1 月 1 日起) 在 Core Data SQLite 文件中,可以简单地检查两者之间的区别 出发和到达日期至少为 3600 秒:

let predicate = NSPredicate(format: "arrivalDate - departureDate >= 3600")
fetchRequest.predicate = predicate

这在我的测试中按预期工作。如果最短行程时间 在运行时确定,使用

let minDuration = 3600
let predicate = NSPredicate(format: "arrivalDate - departureDate >= %@", minDuration as NSNumber)

备注:以上谓词仅在核心数据中使用时才有效 获取请求。以下变体适用于核心数据 获取请求并使用直接评估的谓词:

 NSPredicate(format: "arrivalDate.timeIntervalSinceReferenceDate - departureDate.timeIntervalSinceReferenceDate >= 3600")