Get device location (only country) in iOS

2019-01-08 06:10发布

I need to get the country location of a iOS device.

I've been trying to use CoreLocation with MKReverseGeocoder. However this seems to return erraneous quite frequently. And I only need the country, no need for streets and such.

How can this be done in a more stable way?

12条回答
混吃等死
2楼-- · 2019-01-08 06:23

If you are only interested in telephone devices, then the technique mentioned here might be useful to you: Determine iPhone user's country

查看更多
劳资没心,怎么记你
3楼-- · 2019-01-08 06:24

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.

查看更多
狗以群分
4楼-- · 2019-01-08 06:29

Here's an alternative, perhaps overly circuitous method. The other solutions are based on manual settings (NSLocale) or on requesting for permission to use location services which can be denied (CLLocationManager), so they have drawbacks.

You can get the current country based on the local timezone. My app is interfacing with a server running Python with pytz installed, and that module provides a dictionary of country codes to timezone strings. I only really need to have the server know the country so I don't have to set it up entirely on iOS. On the Python side:

>>> import pytz
>>> for country, timezones in pytz.country_timezones.items():
...     print country, timezones
... 
BD ['Asia/Dhaka']
BE ['Europe/Brussels']
BF ['Africa/Ouagadougou']
BG ['Europe/Sofia']
BA ['Europe/Sarajevo']
BB ['America/Barbados']
WF ['Pacific/Wallis']
...

On the iOS side:

NSTimeZone *tz = [NSTimeZone localTimeZone];
DLog(@"Local timezone: %@", tz.name); // prints "America/Los_Angeles"

I have my server send in the local timezone name and look it up in the pytz country_timezones dictionary.

If you make an iOS version of the dictionary available in pytz or some other source, you can use it to immediately look up the country code without the help of a server, based on timezone settings, which are often up to date.

I may be misunderstanding NSLocale though. Does it give you the country code through regional formatting preferences or timezone settings? If the latter, then this is just a more complicated way of getting the same result...

查看更多
相关推荐>>
5楼-- · 2019-01-08 06:30

Here's a quick loop in Swift 3 that returns a complete list of country codes.

let countryCode = NSLocale.isoCountryCodes
    for country in countryCode {
        print(country)
    }
查看更多
聊天终结者
6楼-- · 2019-01-08 06:33

@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]);
    }];
}
查看更多
Emotional °昔
7楼-- · 2019-01-08 06:33

For Swift 3 it's even simpler:

let countryCode = Locale.current.regionCode
查看更多
登录 后发表回答