4

It appears NSSortDescriptor should be a fairly easy class to work with.

I have stored in CoreData an entity with an attribute of type NSDate appropriately named @"date". I am attempting to apply a sort descriptor to a NSFetchRequest and it doesn't appear to be returning the results I had hoped for.

The result I am hoping for is to simply arrange the dates in chronological order, and instead they are returned in the order for which they were added to CoreData.

Perhaps you can offer guidance?

Is the parameter 'ascending' what controls the sort?

Some Code:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"Data" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityDesc];

[fetchRequest setFetchBatchSize:10];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];    

[fetchRequest setSortDescriptors:sortDescriptors];

NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
esreli
  • 4,993
  • 2
  • 26
  • 40
  • honestly, I changed the name of the Entity. It's not data.. but that's not the important part – esreli Aug 27 '12 at 16:26
  • what are the inputs? what is the output? – holex Aug 27 '12 at 16:47
  • Inputs? They are NSDates, true to the attribute type. Outputs? An array of NSDates. I'm not really sure how to answer your question – esreli Aug 27 '12 at 17:15
  • Your fetchRequest is correct and Yes the ascending controls the sort order. Could you provide some more infos on the entities and the result? – Bernd Rabe Aug 27 '12 at 18:51
  • 1
    Seems to me that `sortedArrayUsingSelector:@selector(compare:)` would be (much) simpler. – Hot Licks Aug 27 '12 at 20:51

4 Answers4

3

Here is more information on NSSortDescriptors

Or if you want to sort an array of dates after getting them for coreDate:

//This is how I sort an array of dates.
NSArray *sortedDateArray = [dateArray sortedArrayUsingFunction:dateSort context:NULL];

// This is a sorting function
int dateSort(id date1, id date2, void *context)
{    
    return [date1 compare:date2];
}

Here is code straight from apple for sorting integers (just modify to sort dates):NSComparator

NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {

    if ([obj1 integerValue] > [obj2 integerValue]) {
        return (NSComparisonResult)NSOrderedDescending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
}];
Jaybit
  • 1,864
  • 1
  • 13
  • 20
  • `[date1 date2]` ? I think you mean `[date1 compare:date2]`;. Also, surely the Function parameter requires an `@selector()` rather than the name of the method? Furthermore, you can just return `[date1 compare:date2]`, rather than iterating through all the possible return values. – max_ Aug 27 '12 at 16:36
  • True didn't think about that when I stripped the code for this. – Jaybit Aug 27 '12 at 16:40
  • this enumerates through all objects in the array? – esreli Aug 27 '12 at 17:35
  • Yes calling "sortedArrayUsingFunction: context:" will enumerate through each item in the array. If the array is not just Dates, lets say its an array of NSDictionarys you can modify the dateSort function to pull the date from the dictionary. – Jaybit Aug 27 '12 at 17:45
  • I would just use a block, not a function. C-Functions, when used like this are a bad idea in objective-c code, as they can lead to linker errors. – Richard J. Ross III Aug 27 '12 at 18:29
  • I added a NSComparator block, as an alternative. – Jaybit Aug 27 '12 at 18:44
3

Separate sort routines (functions or blocks) look like overkill to me. I am routinely sorting Core Data entities by date attribtues just with the sort descriptor method you show in your code. It works perfectly every time.

Clearly, there must be some other mistake.

  • Check if the type is set correcly in your managed object model editor, and in the class file (Data.h, in your case).
  • Also, check if you are not manipulating this attribute so that the creation order ensues.
  • Also, make sure you are not mixing up this attribute with another attribute of type NSDate.
Mundi
  • 79,884
  • 17
  • 117
  • 140
  • I would agree with you, it is overkill. Let me address your proposed answers: (a)The attribute in the xcdatamodel is of type date. I have not created an object entity .h or .m because I use standard object types, and it is a basic model. (b)How might I check this? I don't quite understand what you mean. (c)There is no mix-up – esreli Aug 27 '12 at 22:21
  • (b): search for text you would use to reassign the date property, such as `".date ="` or `"setDate:"`. (a): Here is your solution. Create proper `NSManagedObject` subclasses and you are good to go! – Mundi Aug 28 '12 at 06:21
  • (b)it's really a simple hand-off. The date is a property of a custom object of mine, it remains the same after creation (readonly) and is then inserted into a nsmanagedobject.. there's no reassigning. (a)I don't think this is the solution. It's also overkill. They are dates, they save properly and load back out as NSDates properly. What is the additional benefit of subclassing nsmanagedobject? – esreli Aug 28 '12 at 15:51
  • You just gave your own answer!! The date "remains the same after creation". So your sort routine is working after all. :-) It seems (b) is indeed the solution. Test it by changing `ascending` into the opposite. – Mundi Aug 28 '12 at 16:40
0

Add timestamp - String type field in CoreData entity

creationDate

during insertion of the record

  NSManagedObject *newCredetial = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context];[newCredetial setValue:[self getDate] forKey:@"creationDate"];

date function

- (NSString *)getDate{
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
formatter.dateFormat = @"ddMMyyyyhhmmssss";

return [formatter stringFromDate:date];}

and Use Short Description during Fetching module

NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest1 = [[NSFetchRequest alloc] initWithEntityName:@"Name"];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
[fetchRequest1 setSortDescriptors:@[sortDescriptor]];


arrNameInfo = [[managedObjectContext executeFetchRequest:fetchRequest1 error:nil] mutableCopy];
Naman Vaishnav
  • 1,069
  • 1
  • 13
  • 24
-1

just change samle ""date to Date

like in

NSSortDescriptor *sortDescriptor = 
  [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];

change to

NSSortDescriptor *sortDescriptor = 
  [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:YES];

and it works perfectly

biddulph.r
  • 5,226
  • 3
  • 32
  • 47