I have problem with narrowing the Geocoder result. Here is my code:
CLLocationCoordinate2D centerLocation = CLLocationCoordinate2DMake(53, 10);
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter: centerLocation radius:100 identifier:#"de"];
[self.geocoder geocodeAddressString:[NSString stringWithFormat:#"%#%#",textField.text,string] inRegion:region
completionHandler:^(NSArray* placemarks, NSError* error){
//filling the tableView code
}];
From apple docs:
"Specifying a region lets you prioritize the returned set of results
to locations that are close to some specific geographical area"
But if i start tapping the nearest street name i get results from all over the world but not the street i want. I need to put entire street name in the field to get in in placemarks array. How can I get nearest-first result from geocoder?
EDIT:
I don't know if address is a street, postcode, city name or place name. The bahavior is similar to Map app where there is only one textfield to search in all places.
"if i start tapping the nearest street name"
It looks like to me you’re doing a search based on user-entered query. You should use MKLocalSearch from Map Kit to perform searches for locations that a user can describe by name, address or type. Geocoding is used to convert map coordinates to a structured address or vice versa.
To quote the documentation:
Although local search and geocoding are similar, they support
different use cases. Use geocoding when you want to convert between
map coordinates and a structured address, such as an Address Book
address. Use local search when you want to find a set of locations
that match the user’s input.
For example:
MKLocalSearchRequest *request = [MKLocalSearchRequest new];
request.naturalLanguageQuery = #"saint";
request.region = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(48.850354, 2.337341), 500, 500);
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
for (MKMapItem *item in response.mapItems) {
NSLog(#"item.placemark.name = %#", item.placemark.name);
}
}];
And I would get the following results which are correct based on the region i specified:
item.placemark.name = Eglise Saint Sulpice
item.placemark.name = J'Go Saint Germain
item.placemark.name = Terrazza Saint Germain
item.placemark.name = Hôtel Odéon Saint Germain
item.placemark.name = Le Bon Saint Pourcain
item.placemark.name = Hotel Le Relais Saint Germain
item.placemark.name = Piscine Saint Germain
item.placemark.name = Bistrot de la Grille Saint Germain
item.placemark.name = Esprit Saint Germain
item.placemark.name = Hôtel Relais Saint Sulpice
Then, you're free to do anything you want with the results you get.
Related
I have created a MapKit and trying to play around with MKLocalSearch. One thing I noticed in comparison to Apple Maps, is that mklocalsearch is restricted to 10 results. So how does Apple Maps display 15 suggestions under the search bar?
Okay, on to an example. Im trying to find "Barcelona." In Apple Maps it will be suggested after writing just "barc" and it will stay on the suggestion list throughout typing barcelona.
Now in my own Map view, I actually have to type in the full Barcelona to get the suggestion: Spain, Barcelona. On my way I get other suggestions, but nothing like Spain, Barcelona and not like Apple maps.
Any insight on how to get it working and to why Apple Maps work differently (spec. the 15 results vs 10 with mklocalseach)
Here is the code called on textField Changes:
- (IBAction)searchFieldChanged:(UITextField *)sender {
if(self.locationTextfield.text.length>0)
self.tableView.hidden = NO;
else
self.tableView.hidden = YES;
NSString *query = self.locationTextfield.text;
// Create and initialize a search request object.
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = query;
request.region = self.mapsView.region;//we dont want region-specific search results!
//request.region = MKCoordinateRegionMakeWithDistance(self.mapsView.userLocation.location.coordinate,40000000, 15000000);
// Create and initialize a search object.
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
// Start the search and display the results as annotations on the map.
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
{
[placeMarks removeAllObjects];
NSLog(#"p-count: %lu", response.mapItems.count);
for (MKMapItem *item in response.mapItems) {
[placeMarks addObject:item.placemark];
self.tempPlacemark = item.placemark;
NSLog(#"placemark: %#", item.placemark);//.location.coordinate.latitude);
}
//if(placemarks.count==0)
// appDelegate.staticPlacemark = nil;
//[self.mapsView removeAnnotations:[self.mapsView annotations]];
//[self.mapsView showAnnotations:placemarks animated:NO];
[self.tableView reloadData];
}];
}
What you do is a MKLocalSearch using a MKLocalSearchRequest. What Apple in its macOS and iOS map apps does is using the newer MKLocalSearchCompleter class to obtain autocompletion suggestions. These suggestions are used for realtime search and displayed in a UITableView. When the user selects one entry that suggestion is used to initialize a MKLocalSearchRequest to obtain detailled information about this location.
I'm using Apple Maps to get a list of addresses in the local area. However, it seems to be returning results from all over the world, rather than the map region I am specifying.
I am using the following code, and have checked the region to make sure it is 'broadly' the whole of London (see attachment) for mapView with the same parameters. However in my results I sometimes have locations in Germany, USA or South America.
Anyone can see what I'm doing wrong?
MKLocalSearchRequest* request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = searchTerm;
CLLocationCoordinate2D cornerCoordinate = CLLocationCoordinate2DMake(51.5007282, -0.1246263);
request.region = MKCoordinateRegionMakeWithDistance(cornerCoordinate, 50000, 50000);
MKLocalSearch* search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
//results come in here
}];
Map region:
According to the documentation:
Specifying a region does not guarantee that the results will all be
inside the region. It is merely a hint to the search engine.
It's bummer, but there's unfortunately no way to limit the results just to the provided region.
You may consider use a Google Places API for that: https://developers.google.com/places/webservice/autocomplete
Try this solution. Here I think issue is because of the region you specified.
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = searchTerm;
MKCoordinateSpan span = MKCoordinateSpanMake(.1, .1);
CLLocationCoordinate2D cornerCoordinate = CLLocationCoordinate2DMake(51.5007282, -0.1246263);
request.region = MKCoordinateRegionMake(cornerCoordinate, span);
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
}];
In order to avoid the API limits of foursquare or one of the other local search providers, I would like to use MKLocalSearch from iOS 6.1. The following code:
MKLocalSearchRequest *localSearchRequest = [[MKLocalSearchRequest alloc] init];
MKCoordinateRegion localSearchRegion = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake([theLocationChange.latitude floatValue], [theLocationChange.longitude floatValue]), 500.0f, 500.0f);
localSearchRequest.naturalLanguageQuery = #"restaurants";
localSearchRequest.region = localSearchRegion;
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:localSearchRequest];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
{
if (error)
{
NSLog([error localizedDescription]);
}
for (MKMapItem* mapItem in response.mapItems)
{
NSLog(#"mapitem name is: %#",mapItem.name);
}
}];
will correctly fetch and display restaurants near the specified location. If I change localSearchRequest.naturalLanguageQuery to "hotels", it will fetch and display hotels. The same applies for "hospitals", "bars", etc. If, however, I try an empty string, or " ", "*", or "?" for localSearchRequest.naturalLanguageQuery, it returns no results.
If I use the foursquare API and send it a location, I can easily get back a list of venues that includes local businesses of all types. Is there a way to use MKLocalSearch to return all venues or local businesses?
Apple documentation says that localSearchRequest.naturalLanguageQuery to be considered as natural Language query which means, you can type in anything and get the related results to your query. But Apples Maps database may not be returning the values as you expect.
I am trying to Reverse geocode location from Lat/Long value that I get earlier in the App and I would like from this coordinate to find the city name, country name and ISO.
I am currently using CLLocationManager to get actual location information with the folowing code:
//Auto geolocation and find city/country
locationManager.delegate=self;
//Get user location
[locationManager startUpdatingLocation];
[self.geoCoder reverseGeocodeLocation: locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//String to hold address
locatedAtcountry = placemark.country;
locatedAtcity = placemark.locality;
locatedAtisocountry = placemark.ISOcountryCode;
//Print the location to console
NSLog(#"Estas en %#",locatedAtcountry);
NSLog(#"Estas en %#",locatedAtcity);
NSLog(#"Estas en %#",locatedAtisocountry);
[cityLabel setText:[NSString stringWithFormat:#"%#,",locatedAtcity]];
[locationLabel setText:[NSString stringWithFormat:#"%#",locatedAtcountry]];
//Set the label text to current location
//[locationLabel setText:locatedAt];
}];
It is working perfectly but, It is possible to do the same from Long/Lat value that I had already saved in the device and not with the current location like on the actual code ?
Update and solution:
Thanks Mark for the answer, I finally use the following code to get info from saved coordinate:
CLLocation *location = [[CLLocation alloc] initWithLatitude:37.78583400 longitude:-122.40641700];
[self.geoCoder reverseGeocodeLocation: location completionHandler:
^(NSArray *placemarks, NSError *error) {
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//String to hold address
locatedAtcountry = placemark.country;
locatedAtcity = placemark.locality;
locatedAtisocountry = placemark.ISOcountryCode;
//Print the location to console
NSLog(#"Estas en %#",locatedAtcountry);
NSLog(#"Estas en %#",locatedAtcity);
NSLog(#"Estas en %#",locatedAtisocountry);
[cityLabel setText:[NSString stringWithFormat:#"%#",locatedAtcity]];
[locationLabel setText:[NSString stringWithFormat:#"%#",locatedAtcountry]];
//Set the label text to current location
//[locationLabel setText:locatedAt];
}];
Yes. Create a CLLocation object using the initWithLatitude:longitude: method using your saved lat/lon values, and pass that to reverseGeocodeLocation:.
I am surprised that you say this is working (although, if you're on the simulator, location services are simulated anyway, which might be the reason) because when you call startUpdatingLocation, your implementation of CLLocationManagerDelegate methods like locationManager:didUpdateToLocation:fromLocation: get called. (You've implemented these right?) It is only when this (and other) delegate method is called that you can be certain that you have successfully determined the user's location.
You may want to read up on the CLLocationManagerDelegate protocol and on Location Services best practices as documented by Apple.
By default on a map view we can show the user's location. On tapping the annotation pin, it will show "Current Location". But I want to show the address of the user as street, city and country. How can I do it by using CLGeoCoder class?
Do something like this:
CLGeocoder *gc = [[[CLGeocoder alloc] init] autorelease];
[gc reverseGeocodeLocation:locationObject completionHandler:^(NSArray *placemark, NSError *error) {
CLPlacemark *pm = [placemark objectAtIndex:0];
NSDictionary *address = pm.addressDictionary;
// do something with the address, see keys in the remark below
}];
And the relevant docs here:
http://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLPlacemark_class/Reference/Reference.html#//apple_ref/occ/instp/CLPlacemark/addressDictionary