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

时间:2018-08-13 11:35:57

标签: ios swift core-data nsfetchedresultscontroller

我在CoreData中有一个JOURNEY实体。它具有到达日期和离开日期作为属性。

arrivalDate和离开日期都属于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。

在进一步研究此问题时,我发现我们不能在谓词中使用临时属性,因为从persistentStore获取托管对象时这些属性不存在。

  

您不能使用基于瞬时属性的谓词来获取(尽管您可以使用瞬时属性来自己过滤内存中的内容)。 ...总之,但是,如果直接执行获取,通常不应将基于Objective-C的谓词或排序描述符添加到获取请求中。相反,您应该将这些应用于提取结果。

实现此目标的最佳方法是什么?我正在使用FetchedResultsController在UITableView中显示所有旅程

2 个答案:

答案 0 :(得分:2)

您可以尝试以下基于another question的NSPredicate,它实际上将日期转换为NSNumber,然后减去它们,然后比较结果是否大于或等于3600秒。

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

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

答案 1 :(得分:2)

时间戳记以秒为单位(从参考日期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)

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

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