Reputation: 1875
So here is the hierarchy:
NSArray
A contains 3 objects.
Each of those custom objects contains an NSSet
of another custom objects.
Each of those "another custom object"s contains a number.
I want to sort NSArray
A by that number. I would not care of what object in the set was picked up. Any object from that set would be fine.
Any clues on how to do it with NSSortDescriptor
?
Upvotes: 2
Views: 263
Reputation: 539955
Key-Value coding works also with properties (or even instance variables) of custom objects, as shown in the following example. But you have to specify a collection operator that is applied to the set to choose an object for sorting, e.g. @max
, @min
or @avg
.
// The "inner object", containing a number:
@interface Custom1 : NSObject
@property (nonatomic, strong) NSNumber *number;
@end
@implementation Custom1
@end
// The "outer object", containing a set of "inner" objects:
@interface Custom2 : NSObject
@property (nonatomic, strong) NSSet *others; // set of "Custom1 objects.
@end
@implementation Custom2
@end
Now you can do the following:
Custom1 *o1 = [[Custom1 alloc] init];
o1.number = @1;
Custom1 *o2 = [[Custom1 alloc] init];
o2.number = @2;
Custom2 *p1 = [[Custom2 alloc] init];
p1.others = [NSSet setWithObjects:o1, o2, nil];
Custom1 *o3 = [[Custom1 alloc] init];
o3.number = @3;
Custom1 *o4 = [[Custom1 alloc] init];
o4.number = @4;
Custom2 *p2 = [[Custom2 alloc] init];
p2.others = [NSSet setWithObjects:o3, o4, nil];
NSArray *array = @[p1, p2];
// Sort according to maximum number in the inner object set:
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"[email protected]" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:@[sort]];
Upvotes: 3
Reputation: 18253
Since the data are stored in an NSArray
the sort can be done using blocks, known to a sort descriptor as a comparator. Note that this approach does not work with SQLite-backed Core Data fetches, which sort directly on the property value stored in the underlying data base.
There are several ways to go about it, this one is straight forward, bordering on the pedestrian (and I hope I got the data structure right):
NSArray *data = @[
@{@"otherobjects":[NSSet setWithObjects: @{@"num":@2}, @{@"num":@1}, @{@"num":@4}, nil]},
@{@"otherobjects":[NSSet setWithObjects:@{@"num":@7}, @{@"num":@9}, @{@"num":@8}, nil]}
];
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"otherobjects" ascending:NO comparator:^NSComparisonResult(id obj1, id obj2) {
NSNumber *n1 = [[obj1 anyObject] valueForKey:@"num"];
NSNumber *n2 = [[obj2 anyObject] valueForKey:@"num"];
return [n1 compare: n2];
}];
NSArray *sorted = [data sortedArrayUsingDescriptors:@[sd]];
If you want to get fancy, you can implement a method on your custom object which compares two objects, and then create a sort descriptor using that method, or you could declare a read-only property returning for instance the max or min value of the NSSet
, and then simply use a normal sort descriptor on that property.
Upvotes: 2