0

I have an NSMutableArray called self.objectArray, that contains custom objects. Each object holds an NSDictionary and two other string objects. Actually I need to work only with the dictionary. Every dictionary contains a key named keyDate which holds an NSString that look like this: MM/dd/yy HH:mm:ss.

I would like to sort the array based on their keyDate. The object with the oldest date should be the first object and so on. I've found some questions, that looked helpful and I could create the code that you can see below, but I get an error everytime I run it. As I think NSSortDescriptor won't be the right tool since my keys aren't key value compliant.

PNMessage 0x125c0590> valueForUndefinedKey:]: this class is not key value coding-compliant for the key keyDate.'

NSSortDescriptor *dateDescriptor = [NSSortDescriptor
                                    sortDescriptorWithKey:@"keyDate"
                                    ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [self.objectArray
                             sortedArrayUsingDescriptors:sortDescriptors];

self.finallySorted = [sortedEventArray mutableCopy];

If it's possible I would do it with sort descriptor, however I think there should be some other options, but can't figure out its proper implementation.

So I can also catch every object's keyDate with a for loop, but don't know how can I sort them based on the value. I would really appreciate if somebody could show me the right way.

 for(PNMessage *mg in self.objectArray)

        {
           NSLog(@" test log %@", mg.message[@"keyDate"]);
        }

I already checked this answer: How to sort an NSMutableArray with custom objects in it?

but the structure of my object is different.

My first code based on this question, but it doesn't worked. How to sort an NSMutableArray with custom objects in it?

UPDATE: my try based on Kaan's answer (doesn't works yet)

    static NSDateFormatter *formatter = nil;
if(!formatter) {
    formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.object sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
    NSString *date1String = obj1.message[@"keyDate"];
    NSString *date2String = obj1.message[@"keyDate"];
    NSDate *date1 = [formatter dateFromString:date1String];
    NSDate *date2 = [formatter dateFromString:date2String];

    if ( date1 < date2 ) {
        return (NSComparisonResult)NSOrderedAscending;
    } else if ( date1 > date2 ) {
        return (NSComparisonResult)NSOrderedDescending;
    }
    return (NSComparisonResult)NSOrderedSame;
}];
Community
  • 1
  • 1
rihe
  • 3,066
  • 4
  • 26
  • 55

1 Answers1

2

I would consider using the sortedArrayUsingComparator method

Assuming your custom class is called PNMessage:

static NSDateFormatter *formatter = nil;
if(!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setFormat:@"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.objectArray sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
    NSString *date1String = obj1[@"keyDate"];
    NSString *date2String = obj1[@"keyDate"];
    NSDate *date1 = [formatter dateFromString:date1String];
    NSDate *date2 = [formatter dateFromString:date2String];

    return [date1 compare:date2];
}];

Tip: If you decide on following this, make sure you declare your NSDateFormatter instance as static outside of the sorting body, since allocating Formatters in iOS can be very expensive and cause serious performance penalties.

Kaan Dedeoglu
  • 14,005
  • 5
  • 35
  • 40
  • Possibly could you tell me that how can I get the dictionary out? I don't know how should I start it, it's a little bit confusing that why the first two objects needed. – rihe Jul 08 '14 at 17:36
  • 1
    In the sortedArrayUsingComparator method's block, you specify how two instances should be compared - what makes one instance greater, lesser, or equal to another instance. Editing now.. – Kaan Dedeoglu Jul 08 '14 at 18:59
  • It doesn't make sense. No errors, runs well, but don't sort them. Do i need to specify how the intances should be compared? – rihe Jul 08 '14 at 19:19
  • 1
    @vv88 set a breakpoint before returning the comparison results to make sure that NSDate's are successfully allocated. Also you don't need to compare dates by yourself, NSDate already implements the compare method for you. – Kaan Dedeoglu Jul 08 '14 at 19:33
  • It's working, i failed something in a string. Works well. Thank you very much. I really appreciate your help. Just one more question, if i leave the formatter on the same place, won't cause memory issues? – rihe Jul 08 '14 at 19:58
  • The formatter will be allocated the first time this method runs. But after that the formatter will keep living in the same memory location. It will be created only once in applications lifetime – Kaan Dedeoglu Jul 08 '14 at 21:57