This article will show you how to add GPS capability in your iPhone app and retrieve the user’s current location. Also translate the GPS coordinate into street address.
The
Core Location framework provides the necessary Objective-C interfaces for obtaining information about the user’s location. With the GPS coordinate obtained, you can make use of the API to decode the actual street or utilize the Map framework to further display the location on Map.
Add MapKit and CoreLocation framework in your project. Core Location framework, that you’ve just added, allows you to retrieve the user’s current location in the form of latitude and longitude. It can even give you continuous location update if the user is on the move. To work with the Core Location framework, our view controller should conform to the
CLLocationManagerDelegate protocol. This protocol defines methods used to receive location and heading updates from a CLLocationManager object.
Add MapView on your View Controller. Now set the delegate and outlet of your map view. Add MKMapViewDelegate and CLLocationManagerDelegate.
Declare an instance variable and name it as locationManager. The
CLLocationManager is the object that provides you the location data.
Once you initialize a CLLocationManager object, you can simply call the startUpdatingLocation method to the location service. The service will then continuously send your application a stream of location data.
see code below:
// .h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
@interface GPSViewController : UIViewController<MKMapViewDelegate,CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
//to find address of current location
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
@property (strong, nonatomic) IBOutlet MKMapView *myMapView;
@end
// .m File
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.view setBackgroundColor:[UIColor clearColor]];
[self.myMapView setMapType:MKMapTypeStandard];
//self.myMapView.showsUserLocation = YES; // to show pin point on current location
locationManager = [[CLLocationManager alloc]init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
//request for location updates
[locationManager startUpdatingLocation];
//set region
CLLocationCoordinate2D _coordinate = locationManager.location.coordinate;
MKCoordinateRegion extentsRegion = MKCoordinateRegionMakeWithDistance(_coordinate, 50, 50);
extentsRegion.span.latitudeDelta = 0.02f;
extentsRegion.span.longitudeDelta = 0.02f;
extentsRegion.center = _coordinate;
[self.myMapView setRegion:extentsRegion animated:YES];
//set annotation
MKPointAnnotation *annotation = [[MKPointAnnotation alloc]init];
NSString *sttt = [[NSString alloc]initWithFormat:@"%f,%f",_coordinate.latitude,_coordinate.longitude];
annotation.title = @"Main Title";
annotation.subtitle = sttt;
annotation.coordinate = _coordinate;
[self.myMapView addAnnotation:annotation];
geocoder = [[CLGeocoder alloc] init];
}
To capture the location event, we have to implement the delegate methods as defined in the protocol.
#pragma mark - CLLocationManagerDelegate
- (void)locationManager
:(CLLocationManager
*)manager didFailWithError
:(NSError *)error
{
NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(@"didUpdateToLocation: %@", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil)
{
NSLog(@"longitude: %@", [NSString
stringWithFormat:@"%.8f",currentLocation.coordinate.longitude]);
NSLog(@"latitude: %@",
[NSString stringWithFormat:@"%.8f",currentLocation.coordinate.latitude]);
}
// Stop Location Manager
[locationManager stopUpdatingLocation];
/*
// Reverse Geocoding
NSLog(@"Resolving the Address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
NSLog(@"Address: %@", [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country]);
} else {
NSLog(@"%@", error.debugDescription);
}
} ];
*/
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
{
NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
NSLog(@"placemarks=%@",[placemarks objectAtIndex:0]);
CLPlacemark *placemark1 = [placemarks objectAtIndex:0];
NSLog(@"placemark.ISOcountryCode =%@",placemark1.ISOcountryCode);
NSLog(@"placemark.country =%@",placemark1.country);
NSLog(@"placemark.postalCode =%@",placemark1.postalCode);
NSLog(@"placemark.administrativeArea =%@",placemark1.administrativeArea);
NSLog(@"placemark.locality =%@",placemark1.locality);
NSLog(@"placemark.subLocality =%@",placemark1.subLocality);
NSLog(@"placemark.subThoroughfare =%@",placemark1.subThoroughfare);
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
// strAdd -> take bydefault value nil
NSString *strAdd = nil;
if ([placemark.subThoroughfare length] != 0)
strAdd = placemark.subThoroughfare;
if ([placemark.thoroughfare length] != 0)
{
// strAdd -> store value of current location
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark thoroughfare]];
else
{
// strAdd -> store only this value,which is not null
strAdd = placemark.thoroughfare;
}
}
if ([placemark.postalCode length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark postalCode]];
else
strAdd = placemark.postalCode;
}
if ([placemark.locality length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark locality]];
else
strAdd = placemark.locality;
}
if ([placemark.administrativeArea length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark administrativeArea]];
else
strAdd = placemark.administrativeArea;
}
if ([placemark.country length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark country]];
else
strAdd = placemark.country;
}
NSLog(@"Address : %@", strAdd);
}
}];
}
Finding the Address
The CLGeocoder class provides services for converting between a GPS coordinate and the user-readable address of that coordinate. By specify the latitude and longitude of a given location, you can use CLGeocoder to find a user-readable address. The result (i.e. the address) returned by CLGeocoder is saved in a CLPlacemark object.
Back to your Xcode project. Add two instance variables: geocoder and placemark.
see all steps in upper code.
Initialize the “geocoder” in the “viewDidLoad” method.
Update the “didUpdateToLocation” method to include the code for reverse geocoding.
Upon completion of a geocoding request, the completionHandler will be invoked automatically. The resolved address is saved in CLPlacemark array. Placemark data includes information such as the country, state, city, and street address. So we simply pick the CLPlacemark object from the array and show the address in the address label.
You can use the “stopUpdatingLocation” method to disable the location update. we can stop the location update once we retrieve the current location.
Try to run the app again and check out the output message in the output area. You should notice that the “didUpdateToLocation” is called once and stopped.