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