For my iOS application, I need to organize a list of Parse objects by their distance from the user's current location. Each of the Parse objects has an attribute for location, but the location is a regular address in the form of an NSString, rather than GPS coordinates or a CLLocation.
I have two questions for this situation:
How do I find the distance between an NSString location and the user's current location?
How do I query for the distance in Parse (for example, only display the objects within 5 miles)?
Thanks for any help!
To perform distance queries, you need a GeoPoint. There are many ways to look up a GeoPoint given a string address.
You could create an Cloud Code after-save method that uses Google to lookup the GeoPoint and add it to the record. Looking up the GeoPoint from a string is an expensive operation, you only want to do this once for each data point when the data changes.
To attempt to find distance based on a string address within a query (would require every record to be evaluated every time) would unfairly tax the geo-lookup facility and probably be a breach of the terms of use.
Once you have an actual GeoPoint in your data then the query is quite easy, as per the documentation:
To limit the results using distance check out whereKey:nearGeoPoint:withinMiles, whereKey:nearGeoPoint:withinKilometers, and whereKey:nearGeoPoint:withinRadians.
Related
Is it possible to sort returned objects from Backand based on how near the location field of type "point" is to the querying users current location?
From the Backand docs I have only seen support for querying based on a maximum distance from a point but nothing about sorting by geo points.
I was able to create a custom query in Backand which I can hit from the Backand API. Unfortunately in order to sort on the distance of nearby users I need to calculate the distance from the current user to every other user in the database and then sort based on this. Seems very complex - a lot of calculations every time the query is called! Will probably see big performance hits as the database gets larger. Guess it answers this question, but I am hopeful still of finding a better alternative.
It's been a while since I've touched Core Data, and I'm now trying to move app on to it. The data is downloaded as JSON from a server and is stored as a few flat files.
When a user interacts with the app, I load the entire data set for a particular screen (hundreds of entries) into memory at once. The user can then filter the records (in my case, they're venues) by distance to them. (Location is provided by Core Data.)
The user can also filter by several other properties of the Venue managed objects, as well as enter a search term.
I'm looking to combine all of these filters to allow the user to search, sort, and browse the data. I've written code to do all of these things using an NSArray in memory, but performance is poor.
Do I want to use NSPredicate here? I know I can use it for filtering by properties of the NSManagedObjects, but for more transient attributes, such as venue's distance from the user, I'm not sure how this would work.
What are the general steps to achieve this with Core Data?
As far as distance and core data:
Store lat and long independently, query everything in the "square" that has a center at the user, and a inner radius of the search radius (aka, the square that the circle fits inside)
Throw out results in the corners manually in memory
As far as the total query: some and rules in your predicate will do wonders
I use a quadtree for geographic queries. It is much faster than scanning an array. My code is derived from the Wikipedia entry on Quadtrees. There are several blog posts about using quadtrees on a MKMapView. NSPredicate is not a Core Data specific filter. It can be applied to any NSArray. If your data set is large, several hundred points, it will likely run faster than your loop.
It turns out that I do want NSPredicate for most of my filtering criteria, but any way I slice it, Core Data can't sort by location.
Filtering alphabetically can be done with NSFetchedResultsController, and I can also filter by a "type" property and search term.
As noted elsewhere on the internet, a block based NSSortDescriptor won't do what I want, because Core Data requires sort descriptors that can compile down to SQL statements. Further, Core Data doesn't know how to do SQL location calculations.
I'm a new programmer. I know how to get the latitude/longitude and how to save items in core data, but I'm not sure how to save latitude and longitude.
https://www.youtube.com/watch?v=GeM7Zw12wbM
I've been watching this tutorial because I want a similar app, but I want to save latitude and longitude too. Any ideas how to do this?
CoreData supports a wide range of number size values. Apple's preferred data type to store latitude and longitudinal values is a CLLocationDegrees object, which has a typealias of Double. So you would store your latitude and longitude values as Double's inside CoreData.
In terms of how your CoreData NSManagedObjectModel should be set up, it would make the most sense to save the coordinates by location. In this case you would have two entities: a location entity with a name property that stores the location as a string, and a coordinate entity with both a latitude and longitude property that stores their corresponding values as a Double. You would need to create a "one to many" relationship linking your location to your coordinates.
Then to retrieve your coordinates you would send a fetch request to your location entity and then simply retrieve each location of type NSManagedObject's corresponding coordinates.
You said you were a new programmer, so know that CoreData is not something to be taken lightly. I recommend you read through Apple's programming guide for Core Data as it explains how to set up your CoreData stack, NSManagedObjectModel, and how to create relationships between two entities; Which I am thinking you will most likely need to relate your location to your coordinates. Good Luck.
Core Data Programming Guide
I'm trying to make something where you search for something and it shows the locations a map. I am wondering if there is a way to get a unique id for a location (using mapkit and corelocation) so that I can store it for later. After that, when someone searches some locations and the one with the id that is saved is there, I do something else
Basically I need to get a unique id for a certain location to do something to it later. Right now I'm using the latitude and longitude, but I was wondering if there is a better way.
I think you might want to look into MKAnnotation. That way you can create an annotation for each location you want to save and then later retrieve them.
From the MKAnnotation docs:
The MKAnnotation protocol is used to provide annotation-related
information to a map view. To use this protocol, you adopt it in any
custom objects that store or represent annotation data. Each object
then serves as the source of information about a single map annotation
and provides critical information, such as the annotation’s location
on the map. Annotation objects do not provide the visual
representation of the annotation but typically coordinate (in
conjunction with the map view’s delegate) the creation of an
appropriate MKAnnotationView object to handle the display.
A position is identified by its latitude and longitude (and altitude if you consider 3 dimensions).
When you say location, however I assume you mean more than just position. For example, a restaurant and a bar may be at the same position in terms of latitude and longitude, but are different locations when you consider their name, type of business and so on.
If you create a table in Parse to store locations then you can add columns for all of these attributes, and when you save an object to this table, Parse will assign that object a unique identifier. This object is how you will identify and refer to locations in your app.
You can store a position in Parse using a PFGeoPoint, which is simply a convenient way of storing a latitude and longitude (and Parse has support for identifying nearby positions in a query).
I have records in my Core Data store with latitude and longitude properties. Now I need to find the record that is closest to a given location.
In SQL I would do it like:
select t.lat
,t.lon
,(t.lat-varLat) + (t.lon - varLon) diff
from table t
order by diff ASC.
given varLat and varLon are the coordinates of the location I want the closest record to. However I have no clue how to do this in Core Data with an NSPredicate.
The worst thing I can imagine is looping fetchrequests with a predicate that expands a 'search range' around the given (varLat,varLon), and using
longitude BETWEEN %# && latitude BETWEEN %# with 2 arrays (each having center+ and center- radius as array members) as parameters, each time expanding this range until I get a hit.. however, this is far from optimal.
Thanks for your advice.
First, your query is not correct, with an error of up to app. 40%. Your calculation just sums up the lat and long differences. The actual difference, assuming a 2D surface, is sqrt((lat-varlat)^2 + (lon-varLon)^2). On the actual surface the geometry is more complicated, but the difference negligible in most cases.
In Core Data it is not uncommon to fetch all instances and then iterate through them in a loop. The reason is that Core Data uses a mechanism called faulting that will allow you to retrieve a large number of objects without too much memory overhead.