0

I created a NSMutableArray with two elements; the name of a city (string at index 0) and the distance (double at index 1) from my present position.

for (i=0;i<[City count];++i)
{
distanceFromMe = [Location distanceFromLocation:[cityLocation]];
[a addObject:[cityNames objectatIndex:i]];
[a addObject:@(distanceFromMe)]
[cityArray addObject:a]
}

"Chicago", 560.34

"New York", 204.3456

"Syracuse", 50.04

I would like to sort this array by ascending distances.

"Syracuse", 50.04

"New York", 204.3456

"Chicago", 560.34

I used:

[cityArray sortUsingDescriptors:@[ [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES] ]];

But I keep getting an error of an unrecognized selector sent to instance. In my reading it appears that the method does not need a key since there is only one NSNumber in the array element. I've read a number of different threads on this but none seem to apply.

Any help would be appreciated. Using xcode obj-c not swift.

JWWalker
  • 22,385
  • 6
  • 55
  • 76
cavuco
  • 99
  • 1
  • 12
  • I don't use Objective-C (much at least), but it might be helpful if you could show how you're building the array(s) in question. – scg Nov 27 '19 at 20:22
  • changed code above to include – cavuco Nov 27 '19 at 20:36
  • What is the variable `a` in your code? – JWWalker Nov 27 '19 at 20:37
  • Just an array used to create the array of arrays "cityArray" – cavuco Nov 27 '19 at 20:42
  • 2
    "I created a NSMutableArray with two elements; the name of a city (string at index 0) and the distance (double at index 1) from my present position.". Just don't. Use an array of dictionaries, or an array of custom objects. Avoid mixing different kind of objects like that. – Larme Nov 27 '19 at 20:43

2 Answers2

1

I'd do it without using a sort descriptor.

[cityArray sortUsingComparator:
    ^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        NSArray* arr1 = obj1;
        NSArray* arr2 = obj2;
        return [arr1[1] compare: arr2[1]];
    }];
JWWalker
  • 22,385
  • 6
  • 55
  • 76
0

While @JWWalker's solution works, I'd suggest modeling this a little bit differently.

Specifically, create a class to hold the city/distance pairs:

@interface CityDistance
@property(copy) NSString *name;
@property(copy) NSNumber *distance;
@end

@implementation CityDistance
@end

Store each of your city/distance pairs.

CityDistance *cityDistance = [[CityDistance alloc] init];
cityDistance.name = @"New York";
cityDistance.distance = @(560.3);

NSMutableArray <CityDistance *>*cities = [NSMutableArray array];
[cities addObject: cityDistance];

This allows the compiler to do more type checking, you can hang business logic off the class (i.e. maybe a -(NSNumber *)distanceFromCity:(CityDistance *)otherCity; method?), it is less fragile (oops! Forgot to add the distance to my ambiguous array!) and makes the sorting code more clear:

[cityArray sortUsingComparator:
    ^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        CityDistance* city1 = obj1;
        CityDistance* city2 = obj2;
        return [city1.name compare: city2.name];
    }];
bbum
  • 162,346
  • 23
  • 271
  • 359