Easiest iOS GeoLocation Tutorial Ever


Welcome to my new tutorial, the Easiest iOS GeoLocation Tutorial Ever. Why I call this the easiest? Simply because I will provide you the whole project and will teach you direct to the point of the lesson. Let's get started.

The first thing you wanna do, if you are targeting the devices with below iOS 9, is open up the info.plist of your project. And add this key: NSLocationWhenInUseUsageDescription

So it should look like this:


Then the value will be your message when the alertview pops up to the user.

Next, inside the ViewController where you will implement the Reverse GeoLocation Function, you will need to import this library:
#import <CoreLocation/CoreLocation.h>

After that, you'll declare a CLLocationManager and CLLocation object inside your interface, and put a delegate to your interface. So your interface should look exactly like this:
@interface YourViewController () <CLLocationManagerDelegate>
{
    CLLocationManager *locationManager;
    CLLocation *currentLocation;
}

Implement and call this method from wherever you want. Say from ViewDidLoad or inside a selector of your button.
#pragma mark - setupLocationManager
- (void)setupLocationManager {
    locationManager = [CLLocationManager new];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager requestWhenInUseAuthorization];
    
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways)
    {
        [locationManager startUpdatingLocation];
    }
}

Implement this too, this delegate method will determine the current authorization status of you applicaiton.
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    switch (status) {
        case kCLAuthorizationStatusNotDetermined: {
            NSLog(@"User still thinking granting location access!");
        } break;
        case kCLAuthorizationStatusDenied: {
            [self showAlert:YES];
        } break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        case kCLAuthorizationStatusAuthorizedAlways: {
            NSLog(@"user permits location, do nothing...");
            [locationManager startUpdatingLocation];
        } break;
        default:
            break;
    }
}

This delegate, on the other hand, will call our fancy alert controller that I will show you later on. Copy and paste this code. This is quite similar to our last delegate method.
// Usual error if there is no internet connection
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    [self showAlert:NO];
}

We are nearly complete,  this is the most important delegate method for this project/tutorial. This is where you will get your data.
// This is where we get the values of our readable data location
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    // Fancy Loader...
    // [SVProgressHUD showWithStatus:NSLocalizedString(@"Retrieving your location...", nil)];
    
    currentLocation = [locations objectAtIndex:0];
    [locationManager stopUpdatingLocation];
    
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if (!(error))
         {
             CLPlacemark *placemark = [placemarks objectAtIndex:0];

             // now we will get the data
             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];

             /*---- You can also use this properties
              placemark.region);
              placemark.country);
              placemark.locality);
              placemark.name);
              placemark.ocean);
              placemark.postalCode);
              placemark.subLocality);
              placemark.location);
             ------*/

             // dismiss the loader...
             //[SVProgressHUD dismiss];

         }
         
         else
         {
             NSLog(@"Geocode failed with error %@", error);
             //[SVProgressHUD dismiss];
             //return;
         }
     }];
}

Lastly, you copy and paste this fancy Alert Controller.
// OPTIONAL: FANCY ALERTCONTROLLER
- (void)showAlert:(BOOL)isStatusDenied
{
    UIAlertController *noPermissionAlert = [UIAlertController
                                            alertControllerWithTitle:@""
                                            message:@""
                                            preferredStyle:UIAlertControllerStyleAlert];
    
    NSMutableAttributedString *customFontAttrib;
    
    if (isStatusDenied) {
        customFontAttrib = [[NSMutableAttributedString alloc] initWithString:@"Location Services is off!\n Location services are currently disabled. \nTo enable, go to Settings>App_Name>Location>\nWhile Using the App."];
    } else {
        customFontAttrib = [[NSMutableAttributedString alloc] initWithString:@"No Internet Connection!  \n Ooop! Probably there is no internet connection...."];
    }
    
    
    [customFontAttrib addAttribute:NSFontAttributeName
                             value:[UIFont systemFontOfSize:14.0]
                             range:NSMakeRange(22, customFontAttrib.length-22)];
    [customFontAttrib addAttribute:NSFontAttributeName
                             value:[UIFont systemFontOfSize:18.0 weight:10.0]
                             range:NSMakeRange(0, 26)];
    [customFontAttrib addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor]
                             range:NSMakeRange(0,customFontAttrib.length)];
    
    [noPermissionAlert setValue:customFontAttrib forKey:@"attributedTitle"];
    
    UIAlertAction *ok = [UIAlertAction
                         actionWithTitle:@"Ok, I got it!"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             //Do something here
                             [noPermissionAlert dismissViewControllerAnimated:YES completion:nil];
                         }];
    
    [noPermissionAlert addAction:ok];
    
    // UIAlertController BG
    UIView * firstView = noPermissionAlert.view.subviews.firstObject;
    UIView * nextView = firstView.subviews.firstObject;
    nextView.backgroundColor = [UIColor purpleColor];
    
    noPermissionAlert.view.tintColor = [UIColor whiteColor];
    
    [self presentViewController:noPermissionAlert animated:YES completion:nil];
}


The sample project can be downloaded from this LINK.

Post a Comment