Get device location (only country) in iOS

Here is @Denis's and @Matt's answers put together for a Swift 3 solution:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()
    let geoCoder = CLGeocoder()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.requestAlwaysAuthorization()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            locationManager.startMonitoringSignificantLocationChanges()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let currentLocation = locations.first else { return }

        geoCoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in
            guard let currentLocPlacemark = placemarks?.first else { return }
            print(currentLocPlacemark.country ?? "No country found")
            print(currentLocPlacemark.isoCountryCode ?? "No country code found")
        }
    }
}

Don't forget to set the NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in Info.plist as well!


NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];

will get you an identifier like e.g. "US" (United States), "ES" (Spain), etc.


In Swift 3:

let countryCode = NSLocale.current.regionCode

In Swift 2.2:

let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String

Compared to a solution based on CLLocationManager this approach has pros and cons. The primary con is that it doesn't guarantee that this is where the device is physically if the user configures it differently. This can however also be seen as a pro since it instead shows which country a user is mentally/culturally aligned with - so if e.g. I go abroad on vacation then the locale is still set to my home country. However a pretty big pro is that this API doesn't require user permission like CLLocationManager does. So if you haven't already gotten permission to use the user's location, and you can't really justify throwing a popup dialog in the user's face (or they already rejected that popup and you need a fallback) then this is probably the API you want to use. Some typical use cases for this could be personalization (e.g. culturally relevant content, default formats, etc.) and analytics.


@Denis's answer is good -- here is some code putting his answer into practice. This is for a custom class that you have set to conform to the CLLocationManagerDelegate protocol. It's a little simplified (e.g. if the location manager returns multiple locations, it just goes with the first one) but should give folks a decent start...

- (id) init //designated initializer
{
    if (self)
    {
        self.locationManager = [[CLLocationManager alloc] init];
        self.geocoder = [[CLGeocoder alloc] init];
        self.locationManager.delegate = self;
        [self.locationManager startMonitoringSignificantLocationChanges];
    }
    return self;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    if (locations == nil)
        return;

    self.currentLocation = [locations objectAtIndex:0];
    [self.geocoder reverseGeocodeLocation:self.currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
    {
        if (placemarks == nil)
            return;

        self.currentLocPlacemark = [placemarks objectAtIndex:0];
        NSLog(@"Current country: %@", [self.currentLocPlacemark country]);
        NSLog(@"Current country code: %@", [self.currentLocPlacemark ISOcountryCode]);
    }];
}

NSLocale is just a setting about currently used regional settings, it doesn't mean the actual country you're in.

Use CLLocationManager to get current location & CLGeocoder to perform reverse-geocoding. You can get country name from there.