IOSデバイスの国の場所を取得する必要があります。
CoreLocationをMKReverseGeocoderで使用しようとしています。ただし、これは非常に頻繁にエラーを返すようです。そして、私は国だけを必要とし、通りなどは必要ありません。
これをより安定した方法で行うにはどうすればよいですか?
NSLocale
は、現在使用されている地域設定に関する設定であり、実際に居住している国を意味するものではありません。
CLLocationManager
を使用して現在の場所を取得し、CLGeocoder
を使用して逆ジオコーディングを実行します。そこから国名を取得できます。
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
あなたのような識別子を取得します「US」(米国)、「ES」(スペイン)など.
In Swift:
let countryCode = NSLocale.current.regionCode
Swift 2.2:
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String
CLLocationManagerに基づくソリューションと比較すると、このアプローチには長所と短所があります。主な短所は、ユーザーがデバイスを別の方法で構成した場合に、これがデバイスの物理的な場所であることを保証しないことです。しかし、これは代わりにユーザーがどの国に精神的/文化的に調整されているかを示すため、プロと見なすこともできます。休暇で海外に行くと、ロケールはまだ私の母国に設定されています。ただし、かなり大きな利点は、このAPIがCLLocationManagerのようにユーザー権限を必要としないことです。そのため、ユーザーの場所を使用する権限をまだ取得しておらず、ユーザーの顔にポップアップダイアログをスローすることを正当化できない場合(または、既にポップアップを拒否し、フォールバックが必要な場合)、これはおそらくAPIです使用したい。これのいくつかの典型的なユースケースは、パーソナライゼーション(文化的に関連するコンテンツ、デフォルトのフォーマットなど)と分析です。
@Denisの答えは良いです。これが彼の答えを実践するコードです。これは、CLLocationManagerDelegate
プロトコルに準拠するように設定したカスタムクラス用です。これは少し単純化されています(たとえば、ロケーションマネージャーが複数のロケーションを返す場合、最初のロケーションにのみ移動します).
- (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]);
}];
}
以下は、@ Denisと@Mattの回答をまとめてSwiftソリューションにしたものです。
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")
}
}
}
Info.plist
にもNSLocationAlwaysUsageDescription
またはNSLocationWhenInUseUsageDescription
を設定することを忘れないでください!
これは、おそらく過度に遠回りの代替方法です。他のソリューションは、手動設定(NSLocale)または拒否できるロケーションサービスの使用許可の要求(CLLocationManager)に基づいているため、欠点があります。
現地のタイムゾーンに基づいて現在の国を取得できます。私のアプリは、pytzがインストールされたPythonを実行しているサーバーとインターフェースしています。そのモジュールは、タイムゾーン文字列に国コードの辞書を提供します。 iOSで完全にセットアップする必要があります。Python側:
>>> 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']
...
IOS側:
NSTimeZone *tz = [NSTimeZone localTimeZone];
DLog(@"Local timezone: %@", tz.name); // prints "America/Los_Angeles"
サーバーにローカルタイムゾーン名を送信し、pytz country_timezones辞書で検索します。
辞書のiOSバージョンをpytzまたは他のソースで利用できるようにすると、タイムゾーン設定(多くの場合最新)に基づいて、サーバーの助けを借りずにすぐに国コードを検索できます。
NSLocaleを誤解しているかもしれません。地域のフォーマット設定またはタイムゾーン設定を通じて国コードを提供しますか?後者の場合、これは同じ結果を得るためのより複雑な方法です...
NSLocale *countryLocale = [NSLocale currentLocale];
NSString *countryCode = [countryLocale objectForKey:NSLocaleCountryCode];
NSString *country = [countryLocale displayNameForKey:NSLocaleCountryCode value:countryCode];
NSLog(@"Country Locale:%@ Code:%@ Name:%@", countryLocale, countryCode, country);
//Country Locale:<__NSCFLocale: 0x7fd4b343ed40> Code:US Name:United States
Swift 3の場合、さらに簡単です:
let countryCode = Locale.current.regionCode
NSTimeZoneはCLLocationから取得できます: https://github.com/Alterplay/APTimeZones そしてローカルで動作します。
@ロブ
let locale = Locale.current
let code = (locale as NSLocale).object(forKey: NSLocale.Key.countryCode) as! String?
これらのコードを使用して、地域の国コードを取得し、まだ取得していない場合は、電話設定->一般->言語と地域に移動して、希望する地域を設定します
電話デバイスのみに興味がある場合は、ここで説明した手法が役立つ場合があります。 iPhoneユーザーの国を決定する
国コードの完全なリストを返すSwift 3のクイックループを次に示します。
let countryCode = NSLocale.isoCountryCodes
for country in countryCode {
print(country)
}
地域セットごとに国名を取得するためのSwift 4.0コード:
let countryLocale = NSLocale.current
let countryCode = countryLocale.regionCode
let country = (countryLocale as NSLocale).displayName(forKey: NSLocale.Key.countryCode, value: countryCode)
print(countryCode, country)
prints:Optional( "NG")Optional( "ナイジェリア")。 //ナイジェリア地域セット用