Deleting core data objects from a specific section - ios

I have a very weird question, but if I can explain it well, I guess the answer will not be so difficult.
This is my current scenario:
I have a tableView with six fixed sections.
The sections are populated with core data objects.
I am using a transient attribute to decide on which section the object must be shown. This procedure is done in a NSManagedObject subclass. The transient attribute is called sectionIdentifier.
Due to the reason of using a transient attribute to decide on which section should appear every object, I decided to create a special row on each section, with the intention that there will be always at least one row on every section. This option will reduce the problem to have a nil section that would throw exceptions in case of adding or deleting rows, at least this has been a problem sometimes while testing the app.
That means that at the first launch every section has one row (I will call it the special row). And then the user can add/delete rows perfectly.
The problem I have now is that I need this special row to be remove if the section has new rows. At the same time, if the user deletes the last row in the section, the app automatically creates a new special row, so the section is never empty.
I know that this is not the best way to manage it, but due to my iOS knowledge, this is the best way I found to avoid exceptions while adding or removing rows from an empty section.
What I need is to delete the special row from a section when the user has added at least one new row to the section.
The object has a string attribute called quitar and for the special rows: quitar = #"si". This way, all special rows are easy to identify.
I am using this code to delete the special row if there are new rows in the section:
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity=[NSEntityDescription entityForName:#"ToDoItem" inManagedObjectContext:context];
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
[fetch setEntity:entity];
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"quitar like 'si'"];
[fetch setPredicate:predicate];
NSError *fetchError;
NSArray *fetchedData=[self.managedObjectContext executeFetchRequest:fetch error:&fetchError];
for (NSManagedObject *item in fetchedData){
[context deleteObject:item];
}
I was told that you cannot use transient attributes in a NSPredicate, and you can see in my code, that all special rows are deleted, not only the special from the desired section.
I need your help to find a way to delete only the special row from the section I want, not from all the sections.
Thank you and sorry for my english.
EDITED
Please find below the way I assign sectionIdentifier in the NSManagedObject class ToDoItem:
-(NSString *)sectionIdentifier{
[self willAccessValueForKey:#"sectionIdentifier"];
NSString *tmp = [self primitiveValueForKey:#"sectionIdentifier"];
[self didAccessValueForKey:#"sectionIdentifier"];
if (!tmp){
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);
NSDate *today = [NSDate date];
NSDate *date = self.todoDueDate;
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setCalendar:calendar];
[components setYear:2065];
[components setMonth:11];
[components setDay:12];
NSDate *dateFuturoSomeday = [calendar dateFromComponents:components];
NSCalendar *calendar1 = [NSCalendar currentCalendar];
NSDateComponents *components1 = [[NSDateComponents alloc] init];
[components1 setCalendar:calendar1];
[components1 setYear:2065];
[components1 setMonth:11];
[components1 setDay:13];
NSDate *dateFuturoCompleted = [calendar1 dateFromComponents:components1];
NSDateComponents *date1Components = [calendar components:comps
fromDate: today];
NSDateComponents *date2Components = [calendar components:comps
fromDate: date];
NSDateComponents *date3Components = [calendar components:comps
fromDate: dateFuturoSomeday];
NSDateComponents *date4Components = [calendar components:comps
fromDate: dateFuturoCompleted];
today = [calendar dateFromComponents:date1Components];
date = [calendar dateFromComponents:date2Components];
dateFuturoSomeday = [calendar dateFromComponents:date3Components];
dateFuturoCompleted = [calendar dateFromComponents:date4Components];
NSInteger daysAfterToday = [calendar components:NSDayCalendarUnit
fromDate:today toDate:date options:0].day;
// NSString *section;
if (daysAfterToday < 0) {
tmp = #"0";
} else if (daysAfterToday == 0) {
tmp = #"1";
} else if (daysAfterToday > 0 && daysAfterToday < 2) {
tmp = #"2";
}
else if ([self.todoDueDate isEqualToDate:dateFuturoSomeday]){
tmp = #"4";
}
else if ([self.todoDueDate isEqualToDate:dateFuturoCompleted]){
tmp = #"5";
}
else {
tmp = #"3";
}
[self setPrimitiveValue:tmp forKey:#"sectionIdentifier"];
}
return tmp;
}

I have checked that at the cellForRowAtIndexPath method, I am able to detect the value from the transient attribute sectionIdentifier. That means that I can use it to identify the special row item, update the value of another attribute an delete it.
ToDoItem *todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *sec = todoitem.sectionIdentifier;
NSString *quitar = todoitem.quitar;
if ([sec isEqualToString:#"1"] && [quitar isEqualToString:#"si" ] && ( numObjectsSec1 > 1 ) ){
NSLog(#"DAS OBJEKT KANN GELĂ–SCHT WERDEN %#", todoitem.todoName);
NSManagedObjectContext *context = self.managedObjectContext;
[todoitem setValue:#"si se puede borrar" forKey:#"borrar" ];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
[context deleteObject: todoitem];
};

Related

How to reference only the first object in indexPathsForVisibleRows

What I'm trying to do is detect which sections of a UITableView are visible, and then change the date of a calendar based on which are visible.
The issue is that there are typically multiple sections viewable at the same time, and I only want to change the date based on the first section index that appears in visibleRowIndexes, not all of them.
Here's my current implementation (Note: I run this function in cellForRowAtIndexPath):
-(BOOL)whatSectionsAreVisible {
NSArray *visibleRowIndexes = [self.agendaTable indexPathsForVisibleRows];
for (NSIndexPath *index in visibleRowIndexes) {
NSNumber *daySection = #(index.section);
static NSDateFormatter *dateFormatter = nil;
if(!dateFormatter){
dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = #"yyyy-MM-dd"; // Read the documentation for dateFormat
}
// Here is where I will map every index.section to an NSDate
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:daySection.intValue]; // <<== Extract int from daySection
[comps setMonth:6];
[comps setYear:2015];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *date = [gregorian dateFromComponents:comps];
// Update the day selected according to visible section
[[NSNotificationCenter defaultCenter] postNotificationName:#"kJTCalendarDaySelected" object:date];
// Store currentDateSelected
[self.calendar setCurrentDateSelected:date];
NSLog(#"The visible section has an index of: %ld", (long)index.section);
if (index.section == 0) {
NSLog(#"index.row is indeed 0");
return YES;
}
}
return NO;
}
I tried doing something like NSNumber *daySection = #(index[0].section); instead of NSNumber *daySection = #(index.section);, but that doesn't seem to work.
Don't use a loop if you just want the first visible row. Get the first object of visibleRowIndexes as an NSIndexPath. Then get the section from that.
The indexPathsForVisibleRows method returns the index paths in ascending order. So, get rid of the for loop and execute the code in it only for the first object:
NSArray *visibleRowIndexes = [self.agendaTable indexPathsForVisibleRows];
NSIndexPath *index = [visibleRowIndex objectAtIndex:0];

How to count unique dates of CoreData objects?

I need a proper way to count how many unique days there are in CoreData objects with a property of type NSDate.
For example, I have the following:
<Object>.date = "2014-05-15 21:29:12 +0000";
<Object>.date = "2014-05-15 21:49:34 +0000";
<Object>.date = "2014-05-16 13:29:23 +0000";
<Object>.date = "2014-05-16 20:49:50 +0000";
<Object>.date = "2014-05-16 22:01:53 +0000";
<Object>.date = "2014-05-20 03:32:12 +0000";
<Object>.date = "2014-05-20 12:45:23 +0000";
<Object>.date = "2014-05-20 14:15:50 +0000";
<Object>.date = "2014-05-20 20:20:05 +0000";
In this case, the result must be 3 because there are 3 different days, 2014-05-15, 2014-05-16 and 2014-05-20
Any way to deal with this problem?
I tried with NSPredicate but I did not succeed
Thanks!
That's easy. Let me show you what I'm going to do for it.
Group your results with sort description key. This example helps you to understand how it can be realized.
https://developer.apple.com/library/ios/samplecode/DateSectionTitles/Introduction/Intro.html
And then just calculate these groups.
EDIT:
NSDate+Utils.h
- (NSDate *) dateWithoutTime
NSDate+Utils.m
-(NSDate *) dateWithoutTime
{
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:self];
return [calendar dateFromComponents:components];
}
some file
- (NSUInteger) someObjectsCount
{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"SomeObject"];
NSString *key = #"date.dateWithoutTime";
fetchRequest.sortDescriptors = #[[[NSSortDescriptor alloc] initWithKey:key
ascending:YES]];
NSManagedObjectContext *context;
context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchedResultsController *aFetchedResultsController;
aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:key
cacheName:nil];
[aFetchedResultsController performFetch:nil];
return [[aFetchedResultsController sections] count];
}
That's all!
For Swift
One way is to use a set:
let array = ["15-06-2017", "15-08-2017", "15-06-2017", "14-06-2017",
"14-06-2017"]
let unique = Array(Set(array))
// ["15-06-2017", "15-08-2017", "14-06-2017"]
You could also create an extension that filters through the array more explicitly:
extension Array where Element : Equatable {
var unique: [Element] {
var uniqueValues: [Element] = []
forEach { item in
if !uniqueValues.contains(item) {
uniqueValues += [item]
}
}
return uniqueValues
}
}
NOTE
The unique array will be in an unspecified order, and you may need to sort it. Sometimes it's better to just do it yourself by enumerating, you could write an extension.
It might be good to make an extension :
extension Array where Element : Hashable {
var unique: [Element] {
return Array(Set(self))
}
}
There are probably more optimised ways to do what you want, but this way is quick and easy.
As of iOS 8 you can use NSCalendar's startOfDayForDate
I have the same issue in an app of mine and I've never found a predicate that would do that for me.
I currently look through all the objects in the entity and calculate the day for each date and then return an array of unique days. I am considering adding a day attribute to my entity but have not yet tested that concept.
Below is the code that I currently use. Note:
Both methods are class methods in a class called Game
The entity in my model is called Game and the attribute I want to convert to unique days is startDateTime
The returned array contains unique days in reverse sorted order (most recent day first)
If you are not concerned with the actual unique days but only the count of unique days the code is trivial to change to return the count of days ([uniqueDays count])
My code:
+ (NSArray *)allGameStartDaysInManagedObjectContext:(NSManagedObjectContext *)moc {
__block NSArray *gameDates;
// mod cannot be nil
NSParameterAssert(moc);
[moc performBlockAndWait:^{
NSError *error;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Game"];
NSArray *game = [moc executeFetchRequest:request error:&error];
// Check for errors
if (!game) {
// Log errors
NSLog(#"[%# %# %d]", NSStringFromClass([self class]), NSStringFromSelector(_cmd), __LINE__);
NSLog(#"Core Data error: %#", error.localizedDescription);
NSArray *errors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if (errors != nil && errors.count > 0) {
for (NSError *error in errors) {
NSLog(#" Error: %#", error.userInfo);
}
} else {
NSLog(#" %#", error.userInfo);
}
gameDates = nil;
} else if (game.count) {
// Array to hold (at most) all the days of the games in the database
NSMutableArray *days = [[NSMutableArray alloc] initWithCapacity:game.count];
for (Game *games in game) {
// Add only the day to the array
[days addObject:[Game convertDateTimetoDay:games.startDateTime]];
}
// Generate a unique set of dates
NSSet *uniqueDays = [NSSet setWithArray:days];
// Create an array from the unique set
NSMutableArray *uniqueGameDays = [NSMutableArray arrayWithArray:[uniqueDays allObjects]];
// Create the sort descriptor
NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO];
// Sort the array
NSArray *sortedUniqueGameDays = [uniqueGameDays sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortOrder]];
gameDates = [sortedUniqueGameDays copy];
} else {
gameDates = nil;
}
}];
return gameDates;
}
+ (NSDate *)convertDateTimetoDay:(NSDate *)dateTimeToConvert {
// Get the year, month and day components (included era although this only applies to BCE)
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTimeToConvert];
// Add the date with only the selected components to the array
return [[[NSCalendar currentCalendar] dateFromComponents:components] dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
}
You should have a new attribute called "daydate" which is a date set to midnight from your current date and time.
Every time you create/modify one of your objects, operate like this:
NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents *dateComps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
NSDate *daydate = [calendar dateFromComponents:dateComps];
myObject.date = date;
myObject.daydate = daydate;
Then you can operate your fetch (2 options).
Option 1:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"myObject" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"daydate"];
NSExpression *functionExpression = [NSExpression expressionForFunction:#"count:" arguments:#[keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"count for this daydate:"];
[expressionDescription setExpression:functionExpression];
[expressionDescription setExpressionResultType:NSDoubleAttributeType];
NSAttributeDescription *attributeDesc = (entity.attributesByName)[#"daydate"];
[request setPropertiesToFetch:#[attributeDesc, expressionDescription]];
[request setPropertiesToGroupBy:#[attributeDesc]];
[request setResultType:NSDictionaryResultType];
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"array: %#", array);
NSLog(#"%lu", (unsigned long)array.count);
Option 2:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"myObject" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
request.returnsDistinctResults = YES;
request.propertiesToFetch = #[#"daydate"];
request.resultType = NSDictionaryResultType;
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"array: %#", array);
NSLog(#"array count: %lu", (unsigned long)array.count);

NSFetchedController: Displaying Sections out of order

I have three sections for an Events entity:
Upcoming
Today
Past
Here is FRC setup:
- (NSFetchedResultsController *)fetchedResultsController
{
if(_fetchedResultsController!=nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *firstSort = [[NSSortDescriptor alloc] initWithKey:#"modified"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:firstSort, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:#"sectionIdentifier"
cacheName:nil];
self.fetchedResultsController.delegate = self;
return self.fetchedResultsController;
}
Using a Transient property for the Entity, I setup the the sections as:
- (NSString *)sectionIdentifier
{
[self willAccessValueForKey:#"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:#"sectionIdentifier"];
if (!tmp)
{
NSDate *dateToCompare = [self getUTCFormateDate:[self modified]];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* now = [NSDate date];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = #"dd-MM-yyyy";
NSString *stringDate = [format stringFromDate:now];
NSDate *todaysDate = [format dateFromString:stringDate];
NSUInteger differenceInDays =
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:dateToCompare] -
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:todaysDate];
NSString *sectionString;
switch (differenceInDays) {
case -1:
sectionString = #"Past";
break;
case 0:
sectionString = #"Today";
break;
case 1:
sectionString = #"Upcoming";
break;
}
tmp = sectionString;
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
Currently the sections appear in descending order, where Upcoming is first, then Today, and then Past. I'd like to show Today's section first.
How can I display the sections in the following order?
Section 0: Today
Section 1: Upcoming
Section 2: Past
The only thing controlling the order is the sort descriptor you have:
NSSortDescriptor *firstSort = [[NSSortDescriptor alloc] initWithKey:#"modified"
ascending:NO];
So you need to change that. You can make it ascending, but you describe a sort order which isn't directly linked to the date.
Because what you describe is dependent upon the current date you will need to make some modifications so that you have order information stored persistently into the model and which you update each day. You can then add this as your first your sort descriptor to use that, and keep the existing sort descriptor for ordering inside each section.
The information you need to store is as per the comment from #Volker, with a simple index number for each section.

Invalidating section identifier

I am using a transient attribute to sort the core data objects into separate table view sections. It is called 'sectionIdentifier'. The getter for this attribute is inside a NSManagedObject subclass, called ToDoItem.m . The problem is that during app execution, the new added objects are always shown under the TODAY section. After a new launch of the app, all objects are shown under the expected row. I was told by an expert user, that when setting a new object, the sectionIdentifier must be invalidated, but I don't know how to invalidate it. Here is my NSManagedObject subclass code:
#import "ToDoItem.h"
#import "ToDoGroup.h"
#import "ToDoSubItem.h"
#implementation ToDoItem
#dynamic todoDescription;
#dynamic todoName;
#dynamic todoDueDate;
#dynamic sectionIdentifier;
#dynamic todogroup;
#dynamic todosubitems;
-(NSString *)sectionIdentifier{
[self willAccessValueForKey:#"sectionIdentifier"];
NSString *tmp = [self primitiveValueForKey:#"sectionIdentifier"];
[self didAccessValueForKey:#"sectionIdentifier"];
if (!tmp){
NSDate *date = self.todoDueDate;
NSDate *todayDate = [NSDate date];
NSLog(#"date= %#",date);
NSLog(#"todayDate = %#",todayDate);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);
NSDateComponents *date1Components = [calendar components:comps fromDate:date];
NSDateComponents *date2Components = [calendar components:comps fromDate:todayDate];
date = [calendar dateFromComponents:date1Components];
todayDate = [calendar dateFromComponents:date2Components];
if([date
compare:todayDate] == NSOrderedSame) {
tmp = #"1";//TODAY
}
else if([date
compare:todayDate] == NSOrderedDescending){
tmp = #"2";//OVERDUE
}
else if ([date
compare:todayDate] == NSOrderedAscending){
tmp =#"0";//UPCOMING
}
NSLog(#"Tmp= %#",tmp);
[self setPrimitiveValue:tmp forKey:#"sectionIdentifier"];
}
return tmp;
}
#end
Any help is welcome...
The problem is that the section identifier is calculated and cached from the todoDueDate, but not updated automatically when the todoDueDate changes.
The DateSectionTitles/APLEvent.m
sample code from Apple shows how such an automatic update can be achieved.
In your case, you should add the following methods to the managed object subclass
ToDoItem:
- (void)setTodoDueDate:(NSDate *)newDate
{
// If the todoDueDate changes, the section identifier become invalid.
[self willChangeValueForKey:#"todoDueDate"];
[self setPrimitiveValue:newDate forKey:#"todoDueDate"];
[self didChangeValueForKey:#"todoDueDate"];
// Set the section identifier to nil, so that it will be recalculated
// when the sectionIdentifier method is called the next time:
[self setPrimitiveValue:nil forKey:#"sectionIdentifier"];
}
+ (NSSet *)keyPathsForValuesAffectingSectionIdentifier
{
// If the value of todoDueDate changes, the section identifier may change as well.
return [NSSet setWithObject:#"todoDueDate"];
}

Aggregate Operation on Core Data in Table View with count and grouping by date

I have a Core Data database with an entity "Event" and an attribute "eventDate" with "Date" type.
The task is showing events grouping by date and showing the number (#"count") of events date by date. For example eventDate (mm-dd-yyyy) data:
events eventDate
event 1 01-01-2013
event 2 01-01-2013
event 3 01-02-2013
event 4 01-03-2013
...
Result in table view:
date count
01-01-2013 2
01-02-2013 1
01-03-2013 1
...
Don't like to fetch all database as it could be big so I use aggregate operation not to fetch every object.
The code is working without error but the resulting array is empty.
My guess the problem is the grouping with date type attribute and the NSAttribute/attributeType but couldn't make it work.
The code in the Event's category file is:
+ (NSArray *)aggregateOperationOnEvent:(NSString *)attributeName withFunction:(NSString *)function withPredicate:(NSPredicate *)predicate inManagedObjectContext: (NSManagedObjectContext*)context {
NSEntityDescription* entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:context];
NSAttributeDescription* attributeDesc = [entity.attributesByName objectForKey:attributeName];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: attributeName];
NSExpression *functionExpression = [NSExpression expressionForFunction: [NSString stringWithFormat:#"%#:", function] arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: function];
[expressionDescription setExpression: functionExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:#"Event"];
[request setPropertiesToFetch:[NSArray arrayWithObjects:attributeDesc, expressionDescription, nil]];
[request setPropertiesToGroupBy:[NSArray arrayWithObject:attributeDesc]];
[request setResultType:NSDictionaryResultType];
if (predicate != nil)
[request setPredicate:predicate];
NSError* error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
return results;
}
Aggregating on a NSDate is not a good idea, since it's backed by a floating point type. Things might be easier if you store something like days since reference date as an int32_t. You need to use NSDateComponents:
#implementation NSDate (Days)
- (NSInteger)daysSinceReferenceDate;
{
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comp = [cal components:NSDayCalendarUnit fromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:0] toDate:self options:0];
return [comp day];
}
#end
The only problem was when I transferred the "results" array to another array the latter's allocation code accidentally commented out, this is why I got empty array in the NSLog. So the GOOD NEWS it's possible to use aggregate operation on DATE attribute and the solution is above. The "results" array's printout:
2013-02-13 19:19:48.063 YourAppsName[35147:c07] -------- results = (
{
count = 2;
eventDate = "2013-01-01 00:00:00 +0000";
},
{
count = 1;
eventDate = "2013-01-02 00:00:00 +0000";
},
{
count = 1;
eventDate = "2013-01-03 00:00:00 +0000";
}
)

Resources