Reputation: 3639
I have a simple reminder app for plants. I'm trying to sort the data that I get via Core Data's NSFetchedResultsController
. My problem is: the data that I'm trying to sort relies on the manipulation of 2 properties.
I have a Plant
object with these properties: waterCycle
and lastWater
.
waterCycle
is the number (Double
) of days in-between that plant requires water and lastWater
is the date (NSDate
) when the plant was last watered. I have a function that calculates, if the plant is due, how many days late since it required water. (i.e. Needed water 3 days ago!)
After some research, I believe I cannot sort based on computed properties or do anything too funky with fetch requests. I'm trying to achieve this with NSFetchRequest
and NSSortDescriptor
but nothing seems to work. Any suggestions are welcome on how to tackle this challenge.
One alternative I had in mind was that I could keep this data within the object record, but that would imply that the app would need to recompute and save all objects each day in order only to bump that late day number which is pretty cumbersome in my opinion.
Here's some code, do not hesitate to ask for more info or code. Thanks!
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!
}
I calculate the number of late days with a function similar to this (simplified for 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
}
Upvotes: 0
Views: 873
Reputation: 2307
I've struggled with looking for ways to sort NSFetchedResultsController
from a computed property/transient attribute as well and after attempting several hacks found no good option.
If I was tacking this specific problem, I would add an attribute that holds the target date for the plant to be watered, and use this for sorting.
You won't need to calculate this every day, but instead updated this only when the user updates the value for lastWater
- this will be accurate for making sure that results are ordered, and in the view you can calculate on the fly how many days ahead (or behind) you are for the watering schedule.
Upvotes: 3