I have an NSMutableArray of custom objects. The custom object (Tag Class) has an two properties defined as so:
@interface Tag : NSObject
@property (strong, nonatomic) NSString *tid;
@property (strong, nonatomic) NSString *name;
So, I want to sort my NSMutableArray of these Tag objects by the Tag name - how do I do this?
Also, should I sort this array as it gets loaded or sort it each time I read its contents?
There are several ways to sort a mutable array in objective c.
The simplest I have found is using the [NSMutableArray sortUsingFunction:] method.
For your example, something like this should suffice for the sort function
NSComparisonResult sortTagByName(Tag *tag1, Tag *tag2, void *ignore)
{
return [tag1.name compare:tag2.name];
}
here is a full source listing, that you can use to base your solution on:
#import <Foundation/Foundation.h>
@interface Tag : NSObject {
}
@property (strong, nonatomic) NSString *tid;
@property (strong, nonatomic) NSString *name;
@end
@implementation Tag
@synthesize tid;
@synthesize name;
@end
NSComparisonResult sortTagByName(Tag *tag1, Tag *tag2, void *ignore)
{
return [tag1.name compare:tag2.name];
}
@interface stackExDemo : NSObject
@end
@implementation stackExDemo
+(void) demo {
NSMutableArray * array = [NSMutableArray array];
// add your objects here
[array sortUsingFunction:sortTagByName context:nil];
}
@end
Breaking this down into it's relevant components:
The function
NSComparisonResult sortTagByName(Tag *tag1, Tag *tag2, void *ignore)
{
return [tag1.name compare:tag2.name];
}
This is simply a plain C function (i.e. not a method, so you don't need to define it inside an implementation section of any particular class, however it usually makes sense to define it in the class it applies to).
In the example above, I have defined it after the @end for Tag, simply to make it clear that it it is not a class method.
The parameter I have named "ignore" is the "context" for the sort. In this case there is no context, so we are going to ignore it's value.
Since you are sorting based on an NSString property, NSString's compare method is convenient, however you can also manually return one of {NSOrderedAscending, NSOrderedSame, NSOrderedDescending}
Invoking the sort
[array sortUsingFunction:sortTagByName context:nil];
This repeatedly calls your function for each element in the array, to sort the array.
If you want to be more specific about the type of sort, there are a number of other methods in NSString that can do the comparison, here is a "cut and paste" from NSString.h which should get you started if you want to research it further.
- (NSComparisonResult)compare:(NSString *)string;
- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;
- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange;
- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale; // locale arg used to be a dictionary pre-Leopard. We now accepts NSLocale. Assumes the current locale if non-nil and non-NSLocale.
- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string;
- (NSComparisonResult)localizedCompare:(NSString *)string;
- (NSComparisonResult)localizedCaseInsensitiveCompare:(NSString *)string;
In answer to your second question, you would need to do this whenever you have added or moved an element that might cause the array to be unsorted.