Can you use NSSortDescriptor to sort by a non-zero value?

I have the following sort descriptors that sort an array of my business objects ready for display in a table, I start with some example sort code from the previous SO question

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"awardedOn" ascending:NO]; NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor1, sortDescriptor2, nil]; NSArray *sortedArray = [returnable sortedArrayUsingDescriptors:sortDescriptors]; 

The objects that I show everyone will have a title. Only a few will have the awardOn set, which is NSDate.

What I want to do:

  • Sorting the entire array, so all objects with the set "receivedOn" are displayed at the top
  • Within two “sets”, arrange them alphabetically
  • I don't care about the actual cost of the date, I'm more interested in if it exists or not

Something like this (credits, bold, are important for the awarded On)

  • Tall
  • it's better
  • cool
  • Other
  • Other
  • One more
  • One more
+4
source share
3 answers

You should be able to do this using two descriptors, as you first said, first by reward and then by name. However, you need to provide a custom NSSortDescriptor for the assigned assigned class, which looks something like this:

 #define NULL_OBJECT(a) ((a) == nil || [(a) isEqual:[NSNull null]]) @interface AwardedOnSortDescriptor : NSSortDescriptor {} @end @implementation AwardedOnSortDescriptor - (id)copyWithZone:(NSZone*)zone { return [[[self class] alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]]; } - (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 { if (NULL_OBJECT([object1 valueForKeyPath:[self key]])) { if (NULL_OBJECT([object2 valueForKeyPath:[self key]])) return NSOrderedSame; // If both objects have no awardedOn field, they are in the same "set" return NSOrderedDescending; // If the first one has no awardedOn, it is sorted after } if (NULL_OBJECT([object2 valueForKeyPath:[self key]])) { return NSOrderedAscending; // If the second one has no awardedOn, it is sorted after } return NSOrderedSame; // If they both have an awardedOn field, they are in the same "set" } @end 

This will allow you to split the sets: Awesome / Better / Cool and Another / Another One / One More / Another, in your example. After that, you should be fine:

 NSSortDescriptor *sortDescriptor1 = [[AwardedOnSortDescriptor alloc] initWithKey:@"awardedOn" ascending:YES]; NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES]; 

In conclusion, you may need additional work depending on how your “empty” assignable fields look (I assumed in the code above that the field was set to zero). You can look here: fooobar.com/questions/1418687 / ...

+1
source

Two ways are possible:

  • When creating a business object, assign awardedOn date as distantPast if it does not exist, then do the normal sorting of awardedOn and then title .

  • Create a sort descriptor with a custom comparison method that will be called for each of the business objects:

.

 NSSortDescriptor *awardDescriptor = [NSSortDescriptor descriptorWithKey:@"awardedOn" ascending:NO selector:@selector(compareAwardedOn:)]; // In class for business object - (NSComparisonResult)compareAwardedOn:(id)otherBusiness { // return custom NSComparison result after // checking whether either of awardedOn dates are nil. return NSOrderedSame; } 
+1
source

Try using a comparator:

 _finalArray = [_array sortedArrayUsingComparator: ^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) { if([[obj1 valueForKey@ "awardedOn"] lenght] && ![[obj2 valueForKey@ "awardedOn"] lenght]) return NSOrderedDescending; if([[obj2 valueForKey@ "awardedOn"] lenght] && ![[obj1 valueForKey@ "awardedOn"] lenght]) return NSOrderedAscending; return NSOrderedSame; }]; 
0
source

All Articles