I'm working on an application that needs to detect the user's location.
I need to extract the user's country and city codes.
I was able to get the country code using a placemark in locationManager: didUpdateToLocation: fromLocation: as follows:
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
MKPlacemark * mark = [[MKPlacemark alloc] initWithPlacemark:[placemarks objectAtIndex:0]];
NSString * code = mark.countryCode;
NSLog(#"country code: %#", code);
}];
So, is there any solution that helps me find an IATA 3-Letter Code for the user's city ?
I suggest you use the database available at OpenFlights: http://openflights.org/data.html (which #Ben-G linked indirectly).
There is a somewhat 'web service' as a form: http://openflights.org/html/apsearch but I think that given the size of the database (about 9200 entries) it is actually better to import it in the app and query it directly, specially if you are going to query a lot (more queries... more traffic if using a web service, and so more delay and decreased user experience, etc).
Though I wonder why you wouldn't calculate a circle given the user's position and then query the database for any airport within some specific radius. That will give you all airports in the whereabouts and obviously the cities and the country. Getting the airport code(s) given the user's city might give you nothing if the city mainly served by an airport doesn't correspond to the city of the user's location.
Related
I have used CLLocationManager to get the current GPS coordinates of a user.
I need to get the current state where it is.
With internet:
CLGeocoder *gc = [[CLGeocoder alloc] init];
[gc reverseGeocodeLocation:location completionHandler:^(NSArray *placemark, NSError *error)
{
if(!placemark){
/* handle error */
}else{
CLPlacemark *pm = placemark[0];
NSLog(#"%#", pm.administrativeArea);
}
}];
Is there any way I could find out what the state where the user is without internet?
Your question is not very clear, I'll try an answer though.
Generally if you're asking if you can use the (reverse) geocoding API of CLGeocoder when the device is offline, the answer is no, as stated here in the docs:
The computer or device must have access to the network in order for
the geocoder object to return detailed placemark information.
Although, the geocoder stores enough information locally to report the
localized country name and ISO country code for many locations. If
country information is not available for a specific location, the
geocoder may still report an error to your completion block.
If with state, you mean a country or a nation, you at least have the option to hardcode a list of all the world's countries' coordinates in your app (or maybe you can find one online...) and use the location data to calculate the state... sounds like a lot of effort, but would solve your problem...
My code is virtually identical to the following example:
https://github.com/iamamused/Example-MKLocalSearch.git
Here are the important bits:
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet MKMapView *ibMapView;
#end
#implementation ViewController {
MKLocalSearch *localSearch;
MKLocalSearchResponse *results;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[localSearch cancel];
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = searchBar.text;
request.region = self.ibMapView.region;
localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
[self.resultTable reloadData];
}
}
It seems reasonable that when Sutter and Mason aka 600 Sutter St. are inside the map region searching for "600 Sutte" would include the obvious result "600 Sutter St.". I just can't get that to work. I've tried many different streets and I often get results out of state before I get results that are directly in the map region.
Also, "600 Sut" returns irrelevant results, while "600 Su" returns an error 4. Did it really not find anything that starts with "600 Su"?
Am I using this API completely wrong or is it not meant for what I'm trying to do with it?
Map Region for all queries:
600 Sutte
600 Su
I ended up giving up on Apple local search API and switching to Google. Their Place API is exactly what I needed. It finds relevant results quickly and up to 100k requests per day doesn't cost anything.
Auto-complete:
https://developers.google.com/places/documentation/autocomplete
Details (need this for lat, lon):
https://developers.google.com/places/documentation/details
With the help of JSONModel I built it into my iOS app in a few hours.
The results are exactly what I was hoping to see:
#borisz - too few points to comment directly..BEWARE of using Google Places API in your IOS app. Google states in their terms and conditions that any map displaying data fetched from Google Places API needs to be a Google Map. So if you still wish to use their API and search, just make sure that you are also using a Google Map and not Apple's native maps. Hope this helps - goodluck!
Posting this for those who still have similar problem.
You shouldn't use MKLocalSearchRequest() instead use MKLocalSearchCompleter which gives better results and is used in current Apple Maps.
You can learn how to implement in this
answer
I am trying to make a simple app which allows the user to get the longitude and latitude corresponding to a specific address. I want to provide the user with a search box similar to the one in google maps. Specifically I would like some sort of autocompletion to ensure the user enters a valid address. Is it possible to create an instance of google maps search box?
SPGooglePlacesAutocomplete is a simple objective-c wrapper around the Google Places Autocomplete API.
Look at this API from github which might be helpful- https://github.com/spoletto/SPGooglePlacesAutocomplete
Usage shown as per link. Adding the .h file you can have access to the functions which implement the Google places API from within the function. You can set parameters like partial address string, radius, language your app uses, your location (lat,long)
#import "SPGooglePlacesAutocompleteQuery.h"
...
SPGooglePlacesAutocompleteQuery *query = [SPGooglePlacesAutocompleteQuery query];
query.input = #"185 berry str";
query.radius = 100.0;
query.language = #"en";
query.types = SPPlaceTypeGeocode; // Only return geocoding (address) results.
query.location = CLLocationCoordinate2DMake(37.76999, -122.44696)
Then, call -fetchPlaces to ping Google's API and fetch results. The resulting array will return objects of the SPGooglePlacesAutocompletePlace class.
[query fetchPlaces:^(NSArray *places, NSError *error) {
NSLog(#"Places returned %#", places);
}];
It also has a example project which can be used.
I wonder how a request looks like or which class is used to get results like searching with Apple Maps?
I've tried:
[geocoder geocodeAddressString:text
completionHandler:^(NSArray *placemarks, NSError *error)
that only seems to give back one result.
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
that gives back like local stores etc.
How can I get back results like if you type a few letters and you get back the 10 best matching cities?
Its the way as described above. In the end I used Google Maps API search to get the top 10 results that I was looking for.
For the geo-coding part:
MKLocalSearch returns a list of MKMapItems
Every MKMapItem has a MKPlacemark access by calling mapItem.placemark
This is where it gets cool, in placemark you can access the addressDictionary. Inside the addressDictionary, you can find all sorts of geo details such as address, formattedAddress, region, country etc.
MKLocalSearch uses a .naturalLanguageQuery to search its database. The problem with this setup, is that it will return the top 10 based on your current (or specified) location, which makes a search such as 'city' very difficult. Hope this helps!
Most people will remember the old Nokia phones, which showed your current district (cell tower) you are connected to.
Is this information available on iOS? if so, how to fetch this info?
SO I mean when in New York it would for example return "fulton" as the district...
You don't get access to the cell tower information as you described on iOS, however you can always use the CoreLocation framework (MapKit if you also want backward compatibility with iOS 5.0 for some reason) to do a reverse geocode and get as much detail as available.
For iOS 7.0, you use the CLGeocoder object.
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
// Iterate through available placemarks
}];
The location parameter is a CLLocation object you would have received or created for the user's location.
For reverse geocode requests the array in the completion handler will only contain a single placemark. The various properties and their corresponding real-world relations for a placemark object can be found here
The only thing that we can get from the cell tower is from core telephone framework
Obtaining Information About the Cellular Service Provider
allowsVOIP property
carrierName property
isoCountryCode property
mobileCountryCode property
mobileNetworkCode property
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Reference/CoreTelephonyFrameworkReference/_index.html
Apple currently does not provide any public API that reveals cell tower meta data. From the looks of how they approach telephony API design, I don't see this becoming a feature in the future, either.
Check out: Getting cell tower information in an iOS application?