Reputation: 7932
I have around 2500 records in my SQLite
database, each record represents a branch of a well known store in our country, I use distanceFromLocation
to compare distance between the current user's location and a given location like this:
CLLocation* storeLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
double distance = [userLocation distanceFromLocation:storeLocation];
how to use this piece of code (WITH AN EFFICIENT WAY THAT DOES NOT FREEZE UP THE UI) to find the nearest 5 branches among 2500 lat/lon
pairs stored in the local SQLite
database ?
EDIT :
the code here is an excellent example of how to calculate the distance between two points on the database level, so it's very efficient, but however, the code is kinda hard to be implemented 'coz it accesses SQLite and creates queries manually, anybody provides me with a working sample for that code would be highly appreciated.
Upvotes: 0
Views: 920
Reputation: 91
Check out this (efficient) answer and the comment of Kenny Winker:
https://stackoverflow.com/a/6828849/1611723
It was a similar problem and will help you.
Upvotes: 1
Reputation: 3591
However you want to do it, to avoid blocking the UI you have to do this in another thread. You can achieve this in multiple ways. Here's an example with GCD:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *closestFive = [self closestFive];
dispatch_async(dispatch_get_main_queue(), ^{
//Tell yourself something when the process finished
[self closestAre:closestFive];
}
});
[self closestFive] could be naively implemented by looping through the locations, calculating distance, storing them in a dictionary using the CLLocation wrapped in an NSValue as key. Sort that, and return the subarrayWithRange: of that array. There are probably better implementations, but for 2500 elements, which is not that many, this way of doing it will suffice, as long as you do it in a background thread
This could be an implementation of it:
- (NSArray *)closestFive:(CLLocation *)location from:(NSArray *)locations
{
NSMutableArray *distances = [NSMutableArray arrayWithCapacity:locations.count];
for (CLLocation *l in locations) {
NSDictionary *d = @{
@"location" : l,
@"distance" : @([location distanceFromLocation:l])
};
[distances addObject:d];
}
[distances sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
double d1 = [obj1[@"distance"] doubleValue];
double d2 = [obj1[@"distance"] doubleValue];
if (d1 > d2) {
return NSOrderedDescending;
}
else if (d1 < d2) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
return [[distances subarrayWithRange:NSMakeRange(0, 5)] valueForKey:@"location"];
}
Upvotes: 3