27

I need to determine at startup what country a user is in, for an iPhone application. Presumably I will have to turn on location services and do some sort of reverse geocoding. I don't really want to use a third party web service if possible, are there any other suggestions for determining country from what location services provides?

Initially, I only need to check whether the user is inside the US or not, but this may change in the future to add more countries. I understand that location can not always be determined or the user may have location services turned off. Basically, I just need to know if the user is detected as being inside the US, in order to turn off a specific feature.

EDIT: On further reading, it looks like MKReverseGeocoder would be the way to go, except I don't wish to display any maps in my app, which means I'm not allowed to use this.

Ben Williams
  • 4,695
  • 9
  • 47
  • 72

5 Answers5

35

Another trick you can try is checking the carrier’s MCC:

#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>

CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netInfo subscriberCellularProvider];
NSString *mcc = [carrier mobileCountryCode];
zoul
  • 102,279
  • 44
  • 260
  • 354
  • 6
    Apple's documentation says `CTTelephonyNetworkInfo` only gives info about the carrier who offered the SIM card. So this piece of code gives the same result whether you're roaming or not? – phoenies Aug 05 '11 at 14:25
  • Good question. I guess so… – MonsieurDart Apr 10 '13 at 22:53
  • 1
    Yes, this only gives information about the SIM vendor's country. It's useless to detect current country or roaming/non-roaming... you have to use LocatoinServices with Reverse Geocoder to do that (caveat as that Carriers/users have data roaming initially disabled in certain cases). – igraczech Jun 02 '14 at 10:38
23
NSLocale *locale = [NSLocale currentLocale];
NSString *countryCode = [locale objectForKey: NSLocaleCountryCode];

NSString *countryName = [locale displayNameForKey: NSLocaleCountryCode
                         value: countryCode];
vladzz
  • 331
  • 1
  • 10
  • Can users change the locale themselves, making this unreliable? Also, is the locale the same or different to the 'language' setting of the phone? – Andy A Jul 19 '12 at 08:40
  • 1
    This can be changed by the user in Setting > General > International > Region Format. There is a region format and a language setting. – MonsieurDart Apr 10 '13 at 22:55
  • Not all users utilize real residence locale. Should be used with care of that. – AlexeyVMP Jan 19 '15 at 17:34
4

Given the restrictions of MKReverseGeocoder, it seems the only feasible way for me to achieve what I am after is to use a third party service to perform a reverse geocode. I have chosen to go with GeoNames as they seem to be the standard choice.

Ben Williams
  • 4,695
  • 9
  • 47
  • 72
2

The NSLocale object, such as returned by [NSLocale systemLocale], and[NSLocale autoupdatingCurrentLocale]`) contains the value NSLocaleCountryCode. Check it out in the Apple documentation.

Max MacLeod
  • 26,115
  • 13
  • 104
  • 132
Drew C
  • 6,408
  • 3
  • 39
  • 50
  • Surely the user could just change their locale? – Ben Williams Jun 16 '10 at 05:00
  • Locale is just configuration. It has nothing to do with actual location. – Eran Goldin Jan 20 '15 at 11:24
  • This is a user setting, yes, but in many cases that is what the programmer desires. For instance, a user wants her date, time, and currency formatting to stay set for her preferred locale regardless of what country she is physically in. It depends on the use case. – Drew C Mar 31 '15 at 17:08
1

If you don't want to use the Google services provided by the iPhone SDK, couldn't you just store the coordinates of the US of A borders and check whether or not you are inside that?

Here is a relevant question in that case How can I determine whether a 2D Point is within a Polygon?

If the purpose of the limitation is something other than user experience (for example, to enforce complicance with some specific US law), i.e. when the user can not be trused, I would say that you need some more rigorous checking (after all, the user would simply disallow the use of location services otherwise, wouldn't he/she?).

One such approach would be to do an IP lookup, e.g. http://www.maxmind.com/app/geoip_country

Community
  • 1
  • 1
Krumelur
  • 31,081
  • 7
  • 77
  • 119
  • The purpose is to restrict functionality if the user is found to be within the US. If the user has location services turned off or they are found to be outside the US, functionality is not restricted. I know it's easy to get around, but these are the requirements I have - it's more a preference that functionality is restricted rather than a 100% every time requirement. – Ben Williams Jun 15 '10 at 11:15
  • I certainly would be happy to use the Google services provided by the iPhone SDK. Is there something which will give me what I'm after? – Ben Williams Jun 15 '10 at 11:15