views:

441

answers:

2

Hey,

I am sorting stores to get the closest stores. Furthermore I want to know how far away this shop is. The SQL query would look like this:

select *,

6371 * 2 * ATAN2(SQRT(POWER(SIN((RADIANS(?) - RADIANS(latitude))/2),2) + COS(RADIANS(latitude)) * COS(RADIANS(?)) * POWER(SIN((RADIANS(?) - RADIANS(longitude))/2),2)), SQRT(1-POWER(SIN((RADIANS(?) - RADIANS(latitude))/2),2) + COS(RADIANS(latitude)) * COS(RADIANS(?)) * POWER(SIN((RADIANS(?) - RADIANS(longitude))/2),2))) AS DISTANCE

FROM stores
ORDER BY DISTANCE

these question marks would be replaced by the longitude and latitude of the users position. (latitude, latitude, longitude, latitude, latitude, longitude)

How can I achieve this with iPhone SDK using Core Data?

+1  A: 

From what I know of Core Data (at least the ORM) part of it, there is not a way to do aggregate functions or mathematical functions like what you're attempting. One has the ability to do predicates which equate to the WHERE clause, but not selection functions.

I believe that one could bypass Core Data and do that in sqlite.

Jack

Jack Cox
In fact, you can't, because sqlite doesn't have the necessary trig functions. However, see http://www.thismuchiknow.co.uk/?p=71. That's adding a custom C function to sqlite, which allows it to calculate distance and be used in a SELECT query.
Don Jones
+3  A: 

CoreData itself can't really do this, because distanceFromCurrentLocation here would be a transient property (and you can't fetch on transient properties). But you can still do this in a natural way by fetching the objects into an NSMutableArray, and then sorting that array based on a distanceFromCurrentLocation transient property.

Depending on how often you do this and how often the user moves far enough to require recalculation, it could be more efficient to occasionally recalculate a -currentDistance persistent property, and then using simple predicates. This is a very efficient solution if you search much more often the user moves, because you can easily keep a single locationOfLastRecalculation persistent variable and only recalculate once when the user moves sufficiently. Since this would persist over restarts, the overall performance improvement over dynamic calculation could be substantial.

Rob Napier