I develop an application which uses Core Data. In one UITableView, I want to display a list of my entities, sorted by the saved date of the objects. When I do this:
fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"date"
cacheName:nil];
I get for each object a new section because this code groups the dates according to the seconds, too. But I want a list of the objects, grouped by date, but only according to the day, month and year. Is it possible and how?
Thank you very much for your help!! ;)
This should do the trick for you:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *rawDateStr = [[[self.fetchedResultsController sections] objectAtIndex:section] name];
// Convert rawDateStr string to NSDate...
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZ"];
NSDate *date = [formatter dateFromString:rawDateStr];
// Convert NSDate to format we want...
[formatter setDateFormat:@"d MMMM yyyy"];
NSString *formattedDateStr = [formatter stringFromDate:date];
return formattedDateStr;
}
[EDIT]
Jus saw your comment and for what you are trying to achieve, you could create a transient NSDate
attribute (non persistent) that is formatted in a similar way to the above code (i.e. without H:mm:ss ZZZZ) and use that attribute as your sectionNameKeyPath
value.
So in a nutshell for a foo
object, with fooDate
and fooDateTransient
attributes, you would:
Get your foo.fooDate
attribute
Transform it using the code above (or similar) and assign the NSDate
result to foo.fooDateTransient
Use fooDateTransient
as your sectionNameKeyPath
when creating the fetchedResultsController
object.
PS: I haven't tested this myself but should be worth a shot!
Good luck, Rog
Check out: http://developer.apple.com/library/ios/#samplecode/DateSectionTitles/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009939
It works with month and year, but it's quite easy to make it work with day, month and year.
The following is a Swift 3 solution to sort by date but have section titles corresponding to individual days.
daySectionIdentifier
to your entity in Core Data.NSManagedObject
subclass. Delete the property for daySectionIdentifier
that may get generated in Entity+CoreDataProperties.swift
.To the Entity+CoreDataClass.swift
file, add the following getter for daySectionIdentifier
:
// Transient property for grouping a table into sections based
// on day of entity's date. Allows an NSFetchedResultsController
// to sort by date, but also display the day as the section title.
// - Constructs a string of format "YYYYMMDD", where YYYY is the year,
// MM is the month, and DD is the day (all integers).
public var daySectionIdentifier: String? {
let currentCalendar = Calendar.current
self.willAccessValue(forKey: "daySectionIdentifier")
var sectionIdentifier = ""
if let date = self.date as? Date {
let day = currentCalendar.component(.day, from: date)
let month = currentCalendar.component(.month, from: date)
let year = currentCalendar.component(.year, from: date)
// Construct integer from year, month, day. Convert to string.
sectionIdentifier = "\(year * 10000 + month * 100 + day)"
}
self.didAccessValue(forKey: "daySectionIdentifier")
return sectionIdentfier
}
In your UITableViewController
implementation, add the following method:
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
var sectionTitle: String?
if let sectionIdentifier = fetchedResultsController.sections?[section].name {
if let numericSection = Int(sectionIdentifier) {
// Parse the numericSection into its year/month/day components.
let year = numericSection / 10000
let month = (numericSection / 100) % 100
let day = numericSection % 100
// Reconstruct the date from these components.
var components = DateComponents()
components.calendar = Calendar.current
components.day = day
components.month = month
components.year = year
// Set the section title with this date
if let date = components.date {
sectionTitle = DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .none)
}
}
}
return sectionTitle
}
NSFetchedResultsController
, call the initializer with "daySectionIdentifier"
as the sectionNameKeyPath
parameter.NSFetchedResultsController
's sort descriptor to your entity's plain old "date"
attribute. Importantly, the sort order based on "date"
will be consistent with the sort order based on the section identifier that we just constructed.You should now have your table view grouped into sections by day (e.g., "Feb 6, 2017"), and sorted by fine-grained date.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With