Problem with NSSortDescriptor using custom comparator via selector

Tycho Pandelaar picture Tycho Pandelaar · Mar 15, 2011 · Viewed 8.6k times · Source

I want to use a sortdescriptor with a custom comparator

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] 
    initWithKey:@"object.dateTime" 
    ascending:YES 
    selector:@selector(compareObject:toObject:)];

(the key is a ManagedObject)

Comparator method:

- (NSComparisonResult)compareObject:(id)date1 toObject:(id)date2 {
    NSComparisonResult comparisonResult;
    // Complex comparator contents
    return comparisonResult;
}

However, I get an error: 'NSInvalidArgumentException ', reason: '-[__NSDate compareObject:toObject:]: unrecognized selector sent .....

What am I doing wrong? The comparator works if I use it in a block, but I need it to work via a selector. I can't find any example code or clear documentation on how to use comparators via a selector (for iOS 3.x.x). The documentation talks about comparing to self, but I've tried to incorporate the compare method in object, but that didn't work either.

Who can point me to my problem or to some example code as to how to use this via a selector?

Note: The comparator itself is not a simple date comparison. There is a lot more going on in there.

Answer

Jilouc picture Jilouc · Mar 15, 2011

If you're comparing NSDate objects, the selector you pass has to be a method of the NSDate class and take only one argument.

From the NSSortDescriptor doc:

The selector must specify a method implemented by the value of the property identified by keyPath. The selector used for the comparison is passed a single parameter.

To provide your own sort selector you should define a category on NSDate and place your custom sort method here like

- (NSComparisonResult)customCompare:(id)toDate {
    NSComparisonResult comparisonResult;
    // Complex comparator contents
    return comparisonResult;
}

OR If you don't care about iOS versions < 4.0, you could also use

- (id)initWithKey:(NSString *)key ascending:(BOOL)ascending comparator:(NSComparator)cmptr

cmptr being a block like this:

^(id date1, id date2) {
    NSComparisonResult comparisonResult;
    // Complex comparator contents
    return comparisonResult;
}