diff --git a/Headers/Foundation/NSSortDescriptor.h b/Headers/Foundation/NSSortDescriptor.h index 1f3d608c2..763dee16b 100644 --- a/Headers/Foundation/NSSortDescriptor.h +++ b/Headers/Foundation/NSSortDescriptor.h @@ -50,6 +50,7 @@ extern "C" { NSString *_key; BOOL _ascending; SEL _selector; + NSComparator _comparator; #endif #if GS_NONFRAGILE #else @@ -92,6 +93,24 @@ extern "C" { + (id) sortDescriptorWithKey: (NSString *)aKey ascending: (BOOL)ascending selector: (SEL)aSelector; + +/**

Returns an autoreleased sort descriptor initialized to perform + * comparisons in the specified order using the comparator to compare + * the property aKey of each object.

+ * + *

See also -initWithKey:ascending:selector:.

+ */ ++ (id)sortDescriptorWithKey: (NSString *)key + ascending: (BOOL)ascending + comparator: (NSComparator)cmptr; + +/** + * Initialises the receiver to perform comparisons in the specified order + * using the comparator to compare the property key of each object. + */ +- (id) initWithKey: (NSString *)key + ascending: (BOOL)ascending + comparator: (NSComparator)cmptr; #endif /** Initialises the receiver for comparisons using the 'compare:' selector @@ -102,12 +121,13 @@ extern "C" { /** * Initialises the receiver to perform comparisons in the specified order - * using selector to compar the property key of each object. + * using selector to compare the property key of each object. */ - (id) initWithKey: (NSString *)key ascending: (BOOL)ascending selector: (SEL)selector; + /** Returns the key used to obtain the property on which comparisons are based. */ - (NSString *) key; diff --git a/Source/NSSortDescriptor.m b/Source/NSSortDescriptor.m index a2cf1e0f6..27e8bb575 100644 --- a/Source/NSSortDescriptor.m +++ b/Source/NSSortDescriptor.m @@ -113,8 +113,16 @@ static BOOL initialized = NO; id comparedKey1 = [object1 valueForKeyPath: _key]; id comparedKey2 = [object2 valueForKeyPath: _key]; - result = (NSComparisonResult) [comparedKey1 performSelector: _selector - withObject: comparedKey2]; + if (_comparator == NULL) + { + result = (NSComparisonResult) [comparedKey1 performSelector: _selector + withObject: comparedKey2]; + } + else + { + result = CALL_BLOCK(((NSComparator)_comparator), comparedKey1, comparedKey2); + } + if (_ascending == NO) { if (result == NSOrderedAscending) @@ -132,17 +140,29 @@ static BOOL initialized = NO; - (id) copyWithZone: (NSZone*)zone { + NSSortDescriptor *copy = nil; if (NSShouldRetainWithZone(self, zone)) { return RETAIN(self); } - return [[NSSortDescriptor allocWithZone: zone] - initWithKey: _key ascending: _ascending selector: _selector]; + + if (_comparator == NULL) + { + copy = [[NSSortDescriptor allocWithZone: zone] + initWithKey: _key ascending: _ascending selector: _selector]; + } + else + { + copy = [[NSSortDescriptor allocWithZone: zone] + initWithKey: _key ascending: _ascending comparator: _comparator]; + } + return copy; } - (void) dealloc { TEST_RELEASE(_key); + TEST_RELEASE(_comparator); [super dealloc]; } @@ -167,11 +187,52 @@ static BOOL initialized = NO; selector: aSelector]); } ++ (id)sortDescriptorWithKey: (NSString *)key + ascending: (BOOL)ascending + comparator: (NSComparator)cmptr +{ + return AUTORELEASE([[self alloc] initWithKey: key + ascending: ascending + comparator: cmptr]); + +} + - (id) initWithKey: (NSString *) key ascending: (BOOL) ascending { return [self initWithKey: key ascending: ascending selector: NULL]; } +- (id) initWithKey: (NSString *) key + ascending: (BOOL) ascending + comparator: (NSComparator) cmptr +{ + if ([self init]) + { + if (key == nil) + { + [NSException raise: NSInvalidArgumentException + format: @"%@", _(@"Passed nil key when initializing " + @"an NSSortDescriptor.")]; + } + if (cmptr == NULL) + { + [NSException raise: NSInvalidArgumentException + format: @"%@", _(@"Passed NULL comparator when initializing " + @"an NSSortDescriptor.")]; + } + + ASSIGN(_key, key); + _ascending = ascending; + ASSIGN(_comparator, cmptr); + + return self; + } + else + { + return nil; + } +} + - (id) initWithKey: (NSString *) key ascending: (BOOL) ascending selector: (SEL) selector