Note that there are some explanatory texts on larger screens.

plurals
  1. POobjective-c custom sorting
    text
    copied!<p>So, having struggled with this for too long, without much documentation to go on, I thought I'd share my experience for those few who are even noobier than me. There probably are much cleaner ways of achieving what I did, so please feel free to suggest improvements.</p> <p>Here's what I wanted to do:</p> <p>I have an NSArrayController which manages NSManagedObjects (say Thing). These objects have a name property which is of type NSString. I wanted to sort the array of the array controller using the name of the managed objects. The common way to go about sorting a mutable array of strings should be something like:</p> <pre><code>[myMutableArrayOfStrings sortUsingSelector:@selector(caseInsensitiveCompare:)]; </code></pre> <p>or:</p> <pre><code>NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)]; NSArray *descriptorArray = [NSArray arrayWithObject:sortDescriptor]; [myArrayController setSortDescriptors:descriptorArray]; </code></pre> <p>However, if the names happened to be numbers, caseInsensitiveCompare: would sort 11 before 8 (for instance). Also, I wanted a name of a11b to be sorted AFTER a8b, meaning that I needed to chop the names of the managed objects into groups of digits and non-digit characters, then compare those individually.</p> <p>What I came up with, was to make a category of NSString.</p> <p>header file:</p> <pre><code>#import &lt;Foundation/Foundation.h&gt; @interface NSString (MyString) - (NSComparisonResult)myCustomCompare:(NSString *)anotherString; @end </code></pre> <p>implementation file:</p> <pre><code>#import "MyString.h" @implementation NSString (MyString) - (NSComparisonResult)myCustomCompare:(NSString *)anotherString { elaborate chopping up of strings into substrings.. For each of the 2 strings I made an NSMutableArray. Then I determined if these substrings were NSNumbers, which have their own compare:, or NSStrings (caseInsensitiveCompare:) Then I return an NSComparisonResult (NSOrderedAscending, NSOrderedSame or NSOrderedDescending) } @end </code></pre> <p>Then, in the implementation file of my Thing ManagedObject, I overrid the </p> <pre><code>- (NSComparisonResult)compare:(Thing *)anotherThing { return [self.name myCustomCompare:anotherThing.name]; } </code></pre> <p>One also needs to import MyString.h in the Thing class.</p> <p>Now, using </p> <pre><code>[[myArrayController arrangedObjects] sortUsingSelector:@selector(compare:)]; </code></pre> <p>works like a charm.</p> <p>Just one thing that's been bugging me. If a Thing's name property would contain decimal numbers, like for instance a1.4b and a1.39b, how would I be able to isolate these from the name? (a1.4b would incorrectly be sorted before a1.39b) To make things even worse, a user could enter a Thing's name to be 1.3.55 ...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload