1

My question is based on CLLocationManager and filtering locations within a certain radius.

What I have:

  1. the user's location (Retrieved from CLLocationManager),
  2. a list of say stores in an array, each with its coordinates in lat and long.

My requirement is that I need to filter out stores that are within a 100km radius of the user's given location.

Also, if there are more than 25 stores within the 100km radius, then the logic needs to shift to filtering out the 25 closest stores to my location.

What would be the best way to go about this?

ePerera
  • 56
  • 7
  • You need to use NSComparator. This link http://stackoverflow.com/a/9310464/558000 can give you an idea. – Devang Mar 15 '13 at 05:42

2 Answers2

2

The best option would be to use builtin abilities of many databases to make filtering and ordering for you.

Basic implementation is pretty obvious: just sort the stores and get first 25 that lay within the defined region.

Here is an optimized version of how I'd probably write it given that you may have thousands of stores:

NSArray *stores = ...;
CLLocation *myLocation = ...;

NSMutableArray *nearestStores = [NSMutableArray array];
CLRegion *nearest100kmRegion = [CLRegion initCircularRegionWithCenter:[myLocation coordinate]
                                                               radius:100000
                                                           identifier:@"someIdentifier"];

// We will need to enumerate all stores to ensure that there are no more
// than 25 objects within the defined region.
//
// Since there may be thousands of objects and many of them can be
// out of the defined region, we should perform concurrent enumeration
// for performance reasons.
dispatch_semaphore s = dispatch_semaphore_create(1);
[stores enumerateObjectsWithOptions:NSEnumerationConcurrent
                         usingBlock:^(id store, NSUInteger idx, BOOL *stop)
{
     if ([nearest100kmRegion containsCoordinate:[[store location] coordinate]])
     {
         dispatch_semaphore_wait(s, DISPATCH_FOREVER);
         [nearestStores addObject:store];
         dispatch_semaphore_signal(s);
     }
}];
dispatch_release(s);

if ([nearestStores count] > 25)
{
    [nearestStores sortWithOptions:NSSortConcurrent
                   usingComparator:^(id store1, id store2)
    {
        return [myLocation distanceFromLocation:[store1 location]] - [myLocation distanceFromLocation:[store2 location]];
    }];
}

return [nearestStores subarrayWithRange:NSMakeRange(0, MAX([nearestStores count], 25))];
Kentzo
  • 3,881
  • 29
  • 54
0

See Calculate distance between two latitude-longitude points? (Haversine formula) to determine the distance between 2 lat/long pairs then do this:

Sort the array of stores by the distance to the user and loop through the array to populate a result set. Stop when the result set count is 25 or the distance is greater than 100km.

If the array of stores is really large than you should first populate an array with the stores that are within 100km, then return the entire list if count <= 25 otherwise sort and return the first 25 from the sorted array.

Community
  • 1
  • 1
Nick C
  • 645
  • 3
  • 6