Question

I've a tableViewController that presents a list of places sorted by name! This list is retrieved from my MySQL database using the query

SELECT Name FROM Places ORDER BY Name.

But my goal is to sort them by location according to userLocation. So, Any Place in the database has the fields "latitude" and "longitude". How do I order them by latitude and longitude based on the userLocation?

SELECT Name FROM Places ORDER BY ???.

Clearly latitude and longitude of each places are already inserted into the db. I give the user location as a parameter in the string (and I already have saved in a plist):

[NSString stringWithFormat: @ "SELECT Name FROM ORDER BY Places% @,% @", _myLatitude, _myLongitude "];

Please help me!

Was it helpful?

Solution

First, I suggest you to use a DTO. Something like this:

@interface Place : NSObject
@property(nonatomic, strong) NSString * name;
@property(nonatomic, strong) CLLocationCoordinate2D * coord;
@end

Then use a DAO to get all the places in an NSArray like Anna Karenina suggest you.

@interface PlaceDAO : NSObject
- (NSArray *) places;
- (id) sharedInstance;
@end

Finally you can sort with that:

1. Create a Category of CLLocation to calculate what coord is nearest to a reference coord.

//CLLocation+DistanceComparison.h
static CLLocation * referenceLocation;
@interface CLLocation (DistanceComparison)
- (NSComparisonResult) compareToLocation:(CLLocation *)other;
@end

//CLLocation+DistanceComparison.m
@implementation CLLocation (DistanceComparison)
- (NSComparisonResult) compareToLocation:(CLLocation *)other {
  CLLocationDistance thisDistance = [self distanceFromLocation:referenceLocation];
  CLLocationDistance thatDistance = [other distanceFromLocation:referenceLocation];
  if (thisDistance < thatDistance) { return NSOrderedAscending; }
  if (thisDistance > thatDistance) { return NSOrderedDescending; }
  return NSOrderedSame;
}
@end

2. Add a compare method to your Place DAO.

- (NSComparisonResult)compare:(Place *)otherObject {
    return [self.coord compareToLocation:otherObject.coord];
}

3. Finally sort the array like this.

NSArray * places = [[PlacesDAO sharedInstance] places];
referenceLocation = userLocation;
NSArray * mySortedPlaces = [places sortedArrayUsingSelector:@selector(compare:)];
referenceLocation = nil;

Don't forget add include the category.

OTHER TIPS

Since you already have the latitude and longitude of the places, send the user location (lat & lng) to the stored procedure which you have created. Calculate the distance and try ordering them by the distance.

Refer this article for distance formula.

Ideally, you want to keep this in SQL for speed. You want the Euclidian distance between points, which is basically what Bharadwaj linked -- using the hypotenuse to figure out distances (distance is the square root of the x and y deltas each squared and summed). This is far faster than loading all data out of your MySQL instance and using CLLocation comparisons.

Euclidian distance isn't perfectly accurate -- it refers to distances on a plane, not on the surface of a sphere, but it's probably close enough for your needs.

You should be able to do this math right in your SQL statement.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top