Get all objects within specific range in GeoFire - ios

Is it possible to retrieve all keys within the specific range, using Firebase's GeoFire?
I am aware that you can receive events for geo queries, like: key entered, key exited or key moved, however I am currently looking for something more like FEventTypeValue (one time value read, for the specific geo region), because my map objects are not moving.
Can't find anything in the docs: https://github.com/firebase/geofire-objc

You can use the key entered events to first save all keys for a query in a dictionary and then use the ready event to determine when all keys have been added:
NSMutableDictionary *allKeys = [NSMutableDictionary dictionary];
[query observeEventType:GFEventTypeKeyEntered withBlock:^(NSString *key, CLLocation *location) {
[allKeys setObject:location forKey:key];
}];
[query observeReadyWithBlock:^{
// Create an immutable copy of the keys in the query
NSDictionary *valueData = [allKeys copy];
NSLog(#"All keys within a query: %#", valueData);
}];
Don't forget to clean up your listeners afterwards.

Isn't that exactly what you looking for?
GeoFire allows you to query all keys within a geographic area using GFQuery objects.
Objective-C:
CLLocation *center = [[CLLocation alloc] initWithLatitude:37.7832889 longitude:-122.4056973];
// Query locations at [37.7832889, -122.4056973] with a radius of 600 meters
GFCircleQuery *circleQuery = [geoFire queryAtLocation:center withRadius:0.6];
// Query location by region
MKCoordinateSpan span = MKCoordinateSpanMake(0.001, 0.001);
MKCoordinateRegion region = MKCoordinateRegionMake(center.coordinate, span);
GFRegionQuery *regionQuery = [geoFire queryWithRegion:region];
Swift:
let center = CLLocation(latitude: 37.7832889, longitude: -122.4056973)
// Query locations at [37.7832889, -122.4056973] with a radius of 600 meters
var circleQuery = geoFire.queryAtLocation(center, withRadius: 0.6)
// Query location by region
let span = MKCoordinateSpanMake(0.001, 0.001)
let region = MKCoordinateRegionMake(center.coordinate, span)
var regionQuery = geoFire.queryWithRegion(region)

Related

How to get the distance of multiple location in array from one location and Sort that array by nearest distance in iOS?

I am working on a project in which I have to show the distance of multiple locations from one location. locations are based on latitude and longitude.
I am using the following code to get the distance between two locations is shows nearly same distance
CLLocation *locationA = [[CLLocation alloc] initWithLatitude:28.6379 longitude: 77.2432];CLLocation *locationB = [[CLLocation alloc] initWithLatitude:28.6562 longitude:77.2410];CLLocationDistance distance = [locationA distanceFromLocation:locationB];NSLog(#"Distance is %f",distance);float i = distance/1000;NSLog(#"distance between two places is %f KM", i);
but now i am struct to get the distance of multiple locations from my location: locationA.
for example I take NSArray for latitude and longitude as
NSArray * latitudeArray = [[NSArray alloc]initWithObjects:#"28.6129",#"28.6020",#"28.5244", nil];NSArray * longitudeArray = [[NSArray alloc]initWithObjects:#"77.2295",#"77.2478",#"77.1855", nil];
Please help me to resolve it..
Take locationA as one location..
Please help me to sort the Array by nearest Distance..
First of all, don't create two array for latitude and longitude, It should be one array of CLLocations.
NSMutableArray locationsArray = [[NSMutableArray alloc] init];
//This is just for example, You should add locations to this array according to format of data you have available.
[locationsArray addObject:[[CLLocation alloc] initWithLatitude:28.6379 longitude:77.2432]];
[locationsArray addObject:[[CLLocation alloc] initWithLatitude:28.6020 longitude:77.2478]];
[locationsArray addObject:[[CLLocation alloc] initWithLatitude:28.5244 longitude:77.1855]];
Now, Take some reference location,
CLLocation *yourLocationA ; //set whatever value you have..
You can sort array of location with following.
[locationsArray sortUsingComparator:^NSComparisonResult(CLLocation *obj1Location,CLLocation *obj2Location) {
CLLocationDistance obj1Distance = [obj1Location distanceFromLocation: yourLocationA];
CLLocationDistance obj2Distance = [obj2Location distanceFromLocation: yourLocationA];
return (obj1Distance > obj2Distance);
}];

Distance from UITableView Cells and Current Location

I am creating an iOS application where I have some data structure containing multiple coordinates and I know the current user location. I want to fill the cells of the TableView with the distance from the user's current location to the locations in the TableView.
I was wondering when I should calculate the distance between the user's current location and all the locations in the TableView. Should I calculate all these distances when the application starts? What should I do when the user changes location? Set some sort of timer to check if the user's position changed and recalculate the distances every time the user's position changed?
I should also note, I am giving them the ability to sort this TableView by distance.
Thanks in advance.
You can user CLLocationManagerDelegate's locationManager:didUpdateLocations: Method.
This method is called when user's location will update so you can call your method to show data in tableview from user's current location.
below is some code for sorting your arryOfLocation.
for (int i = 0; i < arrySortByLocation.count; i++)
{
//Current Location Details
NSMutableDictionary *dict = [[arrySortByLocation objectAtIndex:i] mutableCopy];
CLLocationDegrees latitude = [dict[#"city_lat"] doubleValue];
CLLocationDegrees longitude = [dict[#"city_lng"] doubleValue];
CLLocation *location = [[CLLocation alloc]initWithLatitude:latitude longitude:longitude];
CLLocationDistance distance = [appDele.userLocation distanceFromLocation:location];
dict[#"distance"] = [#(distance) stringValue];
//Storing as string since latitude and longitude is also string values
//Since its a dictionary storing as NSNumber is better
[arrySearchLocation setObject:dict atIndexedSubscript:i];
}
//sorting based on distance
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"distance.doubleValue" ascending:YES];
[arrySortByLocation sortUsingDescriptors:#[descriptor]];
}
Hope this will help you..

How to sort array of objects(latitude, longitude) by nearest distance?

I've an array from core data and I'm trying to think how can I sort the array by the nearest distance:
for (int i=0; i<allTasks.count; i++) {
id singleTask = allTasks[i];
double latitude = [singleTask[#"latitude"] doubleValue];
double longitude = [singleTask[#"longitude"] doubleValue];
}
EDIT:
The distance between current location and all the locations in the array.
I know how to calculate the distance, I don't know how to sort them.
So do you want to sort your allTasks array?
The best thing to do would be to add a distance key/value pair to each singleTask object, holding a double NSNumber.
In a first pass, loop through your allTasks array, fetch each lat/long, use it to create a CLLocation, and use the CLLocation method distanceFromLocation: to calculate the distance between each location and your target (current?) location. Save the result into each singleTask object in your array.
Once your allTasks array contains a distance property, simply use one of the sort methods like sortUsingComparator to sort the array based on the distance value. (In the sortUsingComparator family of methods, you provide a comparator block that the system uses to compare pairs of objets. It then runs a sort algorithm on your array, using your comparator to decide on the sort order.
get the CLLocation for your currentPosition (this is done via CLLocationManager)
calculate the distances for each item and store distance+item as a Pair in a Dictionary
Sort Dictionary allKeys array with compare: selector
so
CLLocation *current = ...;
NSMutableDictionary *distsAndTasks [NSMutableDictionary dictionary];
for(id task in allTasks) {
CLLocation *taskLoc = [[CLLocation alloc] initWithLatitude:task.lat longitude:task.long];//!
CLLocationDistance dist = [taskLoc distanceFrom:current];
if(distsAndTasks[#(dist)]) {
NSMutableArray *equidstants = [distsAndTasks[#(dist)] mutableCopy];
[equidstants addObject:task];
distsAndTasks[#(dist)] = equidstants;
}
else {
distsAndTasks[#(dist)] = #[task];
}
}
NSArray *sortedDists = [distsAndTasks.allKeys sortedArrayUsingSelector:#selector(compare:)];
//the tasks can now be access in a sorted way
for(NSNumber *dist in sortedDists) {
NSArray *tasksAtDistance = distsAndTasks[dist];
NSLog(#"%#", tasksAtDistance);
}
You can calculate distance between two points like this
You can also try this https://stackoverflow.com/a/9104926/3151066 and define some way of calculating distance that will satisfy you as the comparison operator

How to sort an array by distance with iOS

I'm still learning objective C and iOS and I'm running into a problem. I am creating an array from CoreData that contains latitudes and longitudes. I want to take this array and sort it by the closest location.
This is what I have so far:
NSError *error = nil;
NSFetchRequest *getProjects = [[NSFetchRequest alloc] init];
NSEntityDescription *projectsEntity = [NSEntityDescription entityForName:#"TimeProjects" inManagedObjectContext:context];
[getProjects setEntity:projectsEntity];
projectArray = [[context executeFetchRequest:getProjects error:&error] mutableCopy];
for (NSObject *project in projectArray) {
// Get location of house
NSNumber *lat = [project valueForKey:#"houseLat"];
NSNumber *lng = [project valueForKey:#"HouseLng"];
CLLocationCoordinate2D coord;
coord.latitude = (CLLocationDegrees)[lat doubleValue];
coord.longitude = (CLLocationDegrees)[lng doubleValue];
houseLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
//NSLog(#"House location: %#", houseLocation);
CLLocationDistance meters = [houseLocation distanceFromLocation:currentLocation];
}
I also have this sorting code but I'm not sure how to put the two together.
[projectArray sortUsingComparator:^NSComparisonResult(id o1, id o2) {
CLLocation *l1 = o1, *l2 = o2;
CLLocationDistance d1 = [l1 distanceFromLocation:currentLocation];
CLLocationDistance d2 = [l2 distanceFromLocation:currentLocation];
return d1 < d2 ? NSOrderedAscending : d1 > d2 ? NSOrderedDescending : NSOrderedSame;
}];
Can some one help me out with making these two things work together?
Your sortUsingComparator block expects CLLocation objects, not instances of your
Core Data class. That would be easy to fix, but what I would recommend is:
Add a transient property currentDistance to your entity. (Transient properties are not stored in the persistent store file.) The type should be "Double".
After fetching the objects, compute the currentDistance for all objects in projectArray.
Finally sort the projectArray array, using a sort descriptor on the currentDistance key.
The advantage is that the distance to the current location is calculated only once for each object, and not calculated repeatedly in the comparator method.
The code would look like this (not compiler checked!):
NSMutableArray *projectArray = ... // your mutable copy of the fetched objects
for (TimeProjects *project in projectArray) {
CLLocationDegrees lat = [project.houseLat doubleValue];
CLLocationDegrees lng = [project.houseLng doubleValue];
CLLocation *houseLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
CLLocationDistance meters = [houseLocation distanceFromLocation:currentLocation];
project.currentDistance = #(meters);
}
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"currentDistance" ascending:YES]
[projectArray sortUsingDescriptors:#[sort]];
Alternatively, you can make currentDistance a persistent property of the entity and calculate it when the object is created or modified. The advantage is that you could add
a sort descriptor based on currentDistance to the fetch request instead of fetching
first and sorting afterwards. The disadvantage is of course that you have to re-calculate
all values when the current location changes.

Checking Proximity of two Locations in IOS

I have an array of locations and when I add another I want to be able to check if the other locations in the array are within a block of the new one. This is the Code I have to find the current location:
//Geocoding Block
[self.geoCoder reverseGeocodeLocation: locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//String to hold address
locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
The array has yet to be created because I want to figure this out first, I dont know what should be held in the array (string...). I know how to do a search I just need to know how to compare the locations.
You can get the distance between two locations using the distanceFromLocation: method on CLLocation. (You can get a CLLocation out of a CLPlacemark with myPlacemark.location.) So if you have an array of CLLocation objects, and you want to find the ones that are within one block (1/20 mile, or about 80 meters), you can do this:
NSMutableArray *locationsWithinOneBlock = [NSMutableArray new];
for (CLLocation *location in myLocations) {
if ([location distanceFromLocation:targetLocation] <= 80.0)
[locationsWithinOneBlock addObject:location];
}
This assumes you have an array myLocations of CLLocation objects that you want to filter against a single CLLocation called targetLocation.

Resources