Objective - C - Current State from GPS - ios

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...

Related

Not getting true GPS data (Altitutde) on iOS devices that HAVE a real GPS

So, I've got a navigation app. It uses the onboard GPS (and magnetic compass and accelerometer) to construct a 3D Augmented Reality viewport similar to how Google Sky works. We're not using ARKit for a variety of reasons including that this device will be used in a moving vehicle and we're concerned that ARKit would get distracted by the apparently non-moving vehicle interior instead of paying attention to the invisibly-moving exterior reference frame outside the vehicle, which is the reference frame we want our AR navigation display to be aligned to.
The AR orientation part is not my main problem (though I am finding that the magcompass plus accelerometers really are fairly prone to error). My vexing issue is that no matter how hard I try, some iOS devices (mostly iPads) don't seem to be using the actual GPS hardware to determine the Core Location data. It seems to be using Wifi trilateration and therefore providing inferior position data (lacking Altitude) and therefore inferior velocity data calculated from the position data.
Here's some facts.
I initialize the Location services like this:
_locationManager = [[CLLocationManager alloc]init];
[_locationManager requestAlwaysAuthorization];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[_locationManager startUpdatingLocation];
On some devices, we definitely get a full 3D GPS location, including altitude.
However, certain test devices ("APPLE MPMF2LL/A iPad Pro with Wi-Fi + Cellular 512GB, 10.5", Silver", "Apple iPad Air 2 MH2V2LL/A (16GB, Wi-Fi + Cellular, Silver) 2014 Model", both with cellular capability and OS 11.2.6), we get Location data that reports a <0 value for Vertical Accuracy, meaning it's not valid, and the Lat/Lon Location value behaves like it's a Wifi trilateration position not a real GPS.
We've tried airplane mode on and off, made sure location services is enabled and permission granted to our app. We tried setting the Location permission to "Always". We tried factory resetting and restoring.
Simple compass apps from other app developers seem to work fine and show a correct altitude and Vertical Accuracy on these devices. Our app seems to work fine on other devices (iPhones of various flavors, full-size 5th gen iPad) and get full GPS Locations. So, it doesn't seem to be a hardware failure of the test devices, yet nor does it seem to be a complete failure of our code.
Is there some magic we aren't requesting or performing properly to ensure we're getting full GPS-sourced location data?
There is already a fallback in the code for devices or circumstances where we can't get GPS Altitude. But if the device HAS the capability, we want to make sure we're using it to the best ability. We also are working on the ability to use external GPSes, but it seems we ought to be able to use what the iOS devices definitely has if we ask for it.
Grateful for any insight. Doesn't seem like it should be this hard.
So, after much pain and suffering, we identified the culprit, but there's still an unknown that is unsolved.
I'll start with the diff of the fix, because reference code trumps all, and then I'll explain what we believe was going wrong.
- CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
- [geocoder reverseGeocodeLocation:_currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
+ if(_udpSocket == nil || timesincelastnetwork > _waitSecondsWithNoNetwork)
{
- if (!(error))
- {
- CLPlacemark *placemark = [placemarks objectAtIndex:0];
- // NSLog(#"\nCurrent Location Detected\n");
- //NSLog(#"placemark %#",placemark);
- NSString *locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
- NSString *Address = [[NSString alloc]initWithString:locatedAt];
- NSString *Area = [[NSString alloc]initWithString:placemark.locality];
- NSString *Country = [[NSString alloc]initWithString:placemark.country];
- NSString *CountryArea = [NSString stringWithFormat:#"%#, %#", Area,Country];
- //NSLog(#"%#",CountryArea);
-
-
- CLLocation* l = placemark.location;
- CLLocationCoordinate2D coords = l.coordinate;
+ _currentLocation = [locations objectAtIndex:0];
+ //[_locationManager stopUpdatingLocation];
-
- float lati = coords.latitude; //39.8560963f; //
- float longi = coords.longitude; //-104.67373759999998f; //
-
- float alti = l.altitude;
So, what appears to have happened is that during the geocoding process, on SOME devices, the altitude was being lost but on some devices it was being preserved. Since we didn't really need the geocoding (we had left it in from the example code in case it would be useful), we just took it out and use the lat/lon/alt directly from the location service and it works properly on all devices now.
I'd consider it a bug or at least an undocumented condition that the geocoder is wiping out the altitude value in some unclear circumstances but not others, but fortunately, it's a bug we are able to work around.

How to make Location auto complete text box Swift ios 8

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.

how to get Geocoding search results like iOS Maps

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!

Fetch location from carrier not lat/lon

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?

Airport codes - iOS

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.

Resources