使用两个属性,使用排序描述符对获取的结果控制器数据进行排序

Posted

技术标签:

【中文标题】使用两个属性,使用排序描述符对获取的结果控制器数据进行排序【英文标题】:Sorting fetched results controller data, using two properties, using sort descriptors 【发布时间】:2017-03-07 20:24:12 【问题描述】:

我有一个简单的植物提醒应用。我正在尝试对通过 Core Data 的NSFetchedResultsController 获得的数据进行排序。我的问题是:我试图排序的数据依赖于对 2 个属性的操作。

我有一个具有以下属性的 Plant 对象:waterCyclelastWater

waterCycle 是植物需要水之间的天数 (Double),lastWater 是植物最后一次浇水的日期 (NSDate)。如果植物到期,我有一个函数可以计算自需要水以来延迟了多少天。 (即 3 天前需要喝水!

经过一些研究,我相信我无法根据计算的属性进行排序,或者对获取请求做任何太时髦的事情。我正在尝试使用NSFetchRequestNSSortDescriptor 来实现这一点,但似乎没有任何效果。欢迎就如何应对这一挑战提出任何建议。

我想到的另一种选择是,我可以将这些数据保存在对象记录中,但这意味着应用程序需要每天重新计算并保存所有对象,以便只增加后期的数字,这很漂亮在我看来很麻烦。

这里有一些代码,不要犹豫,询问更多信息或代码。谢谢!


NSFetchedResultsController

private var fetchedResultsController: NSFetchedResultsController 
    if _fetchedResultsController != nil 
        return _fetchedResultsController!
    

    let fetchRequest = NSFetchRequest()
    fetchRequest.entity = NSEntityDescription.entityForName("Plant", inManagedObjectContext: managedObjectContext!)

    // this should sort the list so plant that needs water are on top
    let waterCycleSortDescriptor = NSSortDescriptor(key: "waterCycle", ascending: true)
    let lastWaterSortDescriptor = NSSortDescriptor(key: "lastWater", ascending: true)

    fetchRequest.sortDescriptors = [waterCycleSortDescriptor, lastWaterSortDescriptor]

    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
                                                               managedObjectContext: managedObjectContext!,
                                                               sectionNameKeyPath: nil, cacheName: PlantRepository.getCacheName())
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    do 
        try _fetchedResultsController!.performFetch()
     catch 
        fatalError("\(error)")
    

    return _fetchedResultsController!


我用类似这样的函数计算迟到天数(为 post 简化):

static func getLateDays(lastWater: NSDate, waterCycle: Double) -> Int 
    // add waterCycle days to lastWater
    let toDate = lastWater.dateByAddingTimeInterval(NSTimeInterval(60*60*24*waterCycle))
    // calc late days after due date
    let lateDays = NSCalendar.currentCalendar().components(NSCalendarUnit.Day, fromDate: toDate, toDate: NSDate(), options: NSCalendarOptions(rawValue: 0))
    return lateDays.day


【问题讨论】:

你的数据集有多大?你是对的,你不能对计算属性进行排序。一种方法是加载整组Plants,然后在内存中对数组进行过滤和排序。 这取决于用户,但最终数据集可能会包含子对象甚至数据(图片)。我曾想过,但这需要在 NSFetchedResultsController 之外进行额外的操作。不过我想这是可能的! 【参考方案1】:

我也一直在努力寻找从计算的属性/瞬态属性中对NSFetchedResultsController 进行排序的方法,并且在尝试了几次 hack 之后发现没有好的选择。

如果我要解决这个特定问题,我会添加一个属性来保存植物浇水的目标日期,并将其用于分类。

您不需要每天计算,而是仅在用户更新 lastWater 的值时才更新此值 - 这对于确保结果排序是准确的,并且在视图中您可以计算苍蝇你提前(或落后)多少天来浇水。

【讨论】:

这是一个有趣的方法。我没想到!这是迄今为止我最接近的解决方案!我会继续挖掘更多,但我最终可能会尝试这个!非常感谢!

以上是关于使用两个属性,使用排序描述符对获取的结果控制器数据进行排序的主要内容,如果未能解决你的问题,请参考以下文章

Swift:按排序描述符对数组进行排序

如何使用 nspredicate 对非英语字符串进行排序?

python类与对象-如何使用描述符对实例属性做类型检查

对获取的结果控制器进行排序,最后是空字符串

如何从按对象创建日期排序的核心数据中获取结果?

JavaScript高级对象相关:对象属性属性描述符(数据属性,存取属性)