简体   繁体   中英

Core Data Group By Year and Sort By Date

I'm new to Core Data (iOS 7), and I'm trying to make the switch from SQL on FMDB to Core Data's ways of fetching data.

I have an Entry entity that has data like this:

flightDate (date) |  duration (float)
-------------------------------------
  2014-05-21      |      1.0
  2014-08-03      |      2.0
  2013-03-27      |      3.0
  2013-09-16      |      4.0
  2012-12-20      |      5.0
-------------------------------------

My end goal is to render this data in a tableView with the year as the section title, and each entry for that year listed underneath it in reverse chronological order. So the data would look like this:

-- 2014 --
Aug 3, 2014     (2.0)
May 21, 2014    (1.0)

-- 2013 --
Sep 16, 2013    (4.0)
Mar 27, 2013    (3.0)

-- 2012 --
Dec 20, 2012    (5.0)

This was easy peasy in SQL, but after hours of research, this is shaping up to be akin to heart surgery without anesthesia in Core Data.

In the end, I'm thinking it would be good to have an NSMutableDictionary like this:

{
  2014 = {
    <Entry: Aug 3, 2014, 2.0>,
    <Entry: May 21, 2014, 1.0>  
  },
  2013 = {
    <Entry: Sep 16, 2013, 4.0>,
    <Entry: Mar 27, 2013, 3.0>  
  },
  2012 = {
    <Entry: Dec 20, 2012, 5.0>
  }
}

...in the right order and ready to pass to my tableView delegates. How can I get from Core Data objects to time-sorted and grouped dictionary data without losing my mind?

Thanks in advance.

Use NSFetchedResultsController .
You can find a working example of breaking a table up into sections based on the date from Apple !

  1. Create an NSFetchRequest. Add a sort descriptor for the date column. That will get your rows in order.
  2. Execute the fetch request on your managed object context, getting back your results
  3. Break each date into components (using something like this .
  4. Iterate, build arrays, whatever you need to do to massage your results into the format you want.

1 will look something like this:

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Entry"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"flightDate" ascending:NO];
fetchRequest.sortDescriptors = @[sortDescriptor];

Core Data stores NSDate s. They're opaque, abstract, timestamps. They don't inherently have a year. The same NSDate will display with a different year depending on your time zone and calendar.

Eg an NSDate that represents GMT 00:01 on the 1st of January, 2001 will display as '2001' on a phone in GMT when properly formatted. It will display as '2000' on a phone in EST. It will display as something very different again if the phone is set to use the Chinese calendar rather than the Gregorian.

It's unclear to me exactly why you would consider this "easy peasy in SQL". Probably you're massively simplifying the problem somehow?

You probably want to add a transient property to return the year. That will be an NSCalendar -driven calculation on the NSDate , involving getting the NSDateComponents .

You can supply the transient property as the sectionNameKeyPath to an NSFetchedResultsController .

However notice the semantics: you don't know what the years are unless you inspect every single thing in the table. So you'll need to fetch every single thing. You'll likely want explicitly to tell your fetch request not to return faults*, for performance reasons, and you're hence not going to get any benefit from Core Data's automatic memory management.

(*) Core Data fetches objects within its graph lazily. Queries ordinarily return faults, which are references to the original object so that it can be found but none of the actual data. But since access to properties is synchronous, that means awful performance if you iterate through faults as though populated — Core Data can't predict which objects you're going to access next so each access is a separate trip to the persistent store.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM