2017-05-17 9 views
8

私はSwift3のアプリケーションで働いています と私は文字の問題があります。私はそれの答えを見つけることができません。Swiftで緯度と経度から市の名前と国を検索

緯度と経度に基づいて都市名と国名を知る方法はありますか?

import UIKit 
import CoreLocation 

class ViewController: UIViewController, CLLocationManagerDelegate{ 
    let locationManager = CLLocationManager() 
    var latitude: Double = 0 
    var longitude: Double = 0 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     // For use when the app is open & in the background 
     locationManager.requestAlwaysAuthorization() 
     // For use when the app is open 
     //locationManager.requestWhenInUseAuthorization() 
     locationManager.delegate = self 
     locationManager.startUpdatingLocation() 
     if CLLocationManager.locationServicesEnabled() { 
      locationManager.delegate = self 
      locationManager.desiredAccuracy = kCLLocationAccuracyBest 
      locationManager.startUpdatingLocation() 
     } 
    } 
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
     if let location = locations.first { 
      print(location.coordinate) 
      latitude = location.coordinate.latitude 
      longitude = location.coordinate.longitude 
     } 
    } 
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { 
     if (status == CLAuthorizationStatus.denied){ 
      showLocationDisabledpopUp() 
     } 
    } 
    func showLocationDisabledpopUp() { 
     let alertController = UIAlertController(title: "Background Location Access Disabled", message: "We need your location", preferredStyle: .alert) 
     let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) 
     alertController.addAction(cancelAction) 
     let openAction = UIAlertAction(title: "Open Setting", style: .default) { (action) in 
      if let url = URL(string: UIApplicationOpenSettingsURLString){ 
       UIApplication.shared.open(url, options: [:], completionHandler: nil) 
      } 
     } 
     alertController.addAction(openAction) 
     self.present(alertController, animated: true, completion: nil) 
    } 
} 
+0

https://developer.apple.com/reference/corelocation/clgeocoder – dan

答えて

11

あなたのプロジェクトにGoogle Maps APIを統合することをお勧めします。そうした場合、Googleが提供するReverse Geocodingを使用してタスクを達成できます。

さらに、IOS開発のためのGoogleにはGoogle Maps SDKがあります。これも検討する価値があります。

UPD:マップをプロジェクトに統合することなく、これを行うことができます。 this答えに基づいて、あなたはGoogle APIへのHTTP要求を使用して達成することができます。要求:

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY 

は、国と都市名を含む要求された場所に関する情報をJSONオブジェクトを返します。

ところで、Alamofireを使用して、Swiftでhttpリクエストを行うことを強くお勧めします。

+0

私は自分のプロジェクトに地図を挿入しません。このコードは[this](http://www.ibm.com)に基づいて@AAliの –

+0

@AAliに使用してください。 /image/gmail/http://www.adobe.com/go/learn_home.html#http://www.aa.com/32758343/4511620)答え、マップを統合せずに簡単に 'Google API 'を使うことができます。httpリクエストを呼び出すために' Alamofire'を使用するだけです。 –

+0

@A.Ali、更新された質問を参照してください。 –

3

CoreLocationのCLGeocoderを使用できます。 Appleのドキュメントから:

地理座標と地名を変換するための単発オブジェクトです。

CLGeocoderクラスは、座標(緯度と経度として指定される)とその座標の使いやすい表現の間で変換するためのサービスを提供します。座標のユーザーフレンドリーな表現は、典型的には、所定の位置に対応する都市、状態、および情報、ストリートから成る...

このサービスは、MapKitに無関係と、などでありますあなたのアプリケーションで地図を使用/表示する必要はありません。

+0

'MKReverseGeocoder'は数年前に廃止されました。 'CLGeocoder'を使うべきです。 – dan

+0

もちろん、あなたは正しいです;) –

+0

私のプロジェクトには地図を挿入しません。このコードを緯度と経度に使用するとリンクする国名が必要です。私はそれを使用します –

4

CLGeocoder reverseGeocodeLocationメソッドを使用してCLPlacemarkを取得し、取得することができますcountrylocalityプロパティ情報です。あなたが逆ジオコーディングと呼ばれている必要がある何

func fetchCountryAndCity(location: CLLocation, completion: @escaping (String, String) ->()) { 
    CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in 
     if let error = error { 
      print(error) 
     } else if let country = placemarks?.first?.country, 
      let city = placemarks?.first?.locality { 
      completion(country, city) 
     } 
    } 
} 

使用

let location = CLLocation(latitude: -22.963451, longitude: -43.198242) 

fetchCountryAndCity(location: location) { country, city in 
    print("country:", country) 
    print("city:", city) 
} 
+0

この非常に便利ですが、名前 –

+0

https://developer.apple.com/reference/corelocation/clplacemark/1423796-isocountrycode国の代わりにisocountrycodeを使用できます –

8

:あなたはその情報を取得する際に、あなたの方法に完了ハンドラを追加する必要がありますので、それは非同期メソッドであることに注意してください。既にあなたは上のいくつかのプロパティを宣言しています。あなたはCLGeocoder & CLPlancemark

let locationManager = CLLocationManager() 
var location: CLLocation? 

let geocoder = CLGeocoder() 
var placemark: CLPlacemark? 

// here I am declaring the iVars for city and country to access them later 

var city: String? 
var country: String? 
var countryShortName: String? 

あなたは場所が

をジオコーディングして完了したら

func startLocationManager() { 
    // always good habit to check if locationServicesEnabled 
    if CLLocationManager.locationServicesEnabled() { 
     locationManager.delegate = self 
     locationManager.desiredAccuracy = kCLLocationAccuracyBest 
     locationManager.startUpdatingLocation() 
    } 
} 

も停止するために別のものを作成するロケーションサービスを開始することができる場所機能を作成を追加する必要があります

func stopLocationManager() { 
    locationManager.stopUpdatingLocation() 
    locationManager.delegate = nil 
} 

in viewLoad or fr OMどこでも場所マネージャdidUpdateLocationsためのデリゲートメソッドを実装するロケーションマネージャは、最初のチェック

override func viewDidLoad() { 
super.viewDidLoad() 

    let authStatus = CLLocationManager.authorizationStatus() 
    if authStatus == .notDetermined { 
     locationManager.requestWhenInUseAuthorization() 
    } 

    if authStatus == .denied || authStatus == .restricted { 
     // add any alert or inform the user to to enable location services 
    } 

    // here you can call the start location function 
    startLocationManager() 

} 

ロケーションマネージャのためのデリゲートメソッドを実装を追加didFailedWithError

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { 
    // print the error to see what went wrong 
    print("didFailwithError\(error)") 
    // stop location manager if failed 
    stopLocationManager() 
} 

を開始したい

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    // if you need to get latest data you can get locations.last to check it if the device has been moved 
    let latestLocation = locations.last! 

    // here check if no need to continue just return still in the same place 
    if latestLocation.horizontalAccuracy < 0 { 
     return 
    } 
    // if it location is nil or it has been moved 
    if location == nil || location!.horizontalAccuracy > lastLocation.horizontalAccuracy { 

     location = lastLocation 
     // stop location manager 
     stopLocationManager() 

     // Here is the place you want to start reverseGeocoding 
     geocoder.reverseGeocodeLocation(lastLocation, completionHandler: { (placemarks, error) in 
       // always good to check if no error 
       // also we have to unwrap the placemark because it's optional 
       // I have done all in a single if but you check them separately 
       if error == nil, let placemark = placemarks, !placemark.isEmpty { 
        self.placemark = placemark.last 
       } 
       // a new function where you start to parse placemarks to get the information you need 
       self.parsePlacemarks() 

      }) 
    } 
} 

parsePlacemarks関数を追加します

parsePlacemarks() { 
    // here we check if location manager is not nil using a _ wild card 
    if let _ = location { 
     // unwrap the placemark 
     if let placemark = placemark { 
      // wow now you can get the city name. remember that apple refers to city name as locality not city 
      // again we have to unwrap the locality remember optionalllls also some times there is no text so we check that it should not be empty 
      if let city = placemark.locality, !city.isEmpty { 
       // here you have the city name 
       // assign city name to our iVar 
       self.city = city 
      } 
      // the same story optionalllls also they are not empty 
      if let country = placemark.country, !country.isEmpty { 

       self.country = country 
      } 
      // get the country short name which is called isoCountryCode 
      if let countryShortName = placemark.isoCountryCode, !countryShortName.isEmpty { 

       self.countryShortName = countryShortName 
      } 

     } 


    } else { 
     // add some more check's if for some reason location manager is nil 
    } 

} 

あなたは数ががsubThoroughfare詳細についてはドキュメントを読み続けると呼ばれている大通り &と呼ばれている+ cmdを使用すると、例の通りの名前のためにアクセスできるすべてのプロパティを表示するCLPlacemarkをクリックする必要があり

注:ここで実装していないジオコーダーエラーも場所を確認する必要がありますが、エラーコードやエラーコードをチェックするのに最適な場所を確認する必要があります。

アップデート:私は国に等しいisoCountryCodeを追加しましたあなたはすでに、位置情報サービスを使用しているAPIとAlamofireをGoogleに呼び出し、余分なネットワークを追加する必要がSHORTNAMEないところparesPlacemarks機能をチェック

3

ここスウィフト4コードです:

var locationManager = CLLocationManager() 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    locationManager.delegate = self 
    locationManager.requestWhenInUseAuthorization() 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest 
    locationManager.startUpdatingLocation() 
    locationManager.startMonitoringSignificantLocationChanges() 
    // Here you can check whether you have allowed the permission or not. 
    if CLLocationManager.locationServicesEnabled() 
    { 
     switch(CLLocationManager.authorizationStatus()) 
     { 
     case .authorizedAlways, .authorizedWhenInUse: 
      print("Authorize.") 
      let latitude: CLLocationDegrees = (locationManager.location?.coordinate.latitude)! 
      let longitude: CLLocationDegrees = (locationManager.location?.coordinate.longitude)! 
      let location = CLLocation(latitude: latitude, longitude: longitude) //changed!!! 
      CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in 
       if error != nil { 
        return 
       }else if let country = placemarks?.first?.country, 
        let city = placemarks?.first?.locality { 
        print(country) 
        self.cityNameStr = city 
       } 
       else { 
       } 
      }) 
      break 

     case .notDetermined: 
      print("Not determined.") 
      self.showAlertMessage(messageTitle: "Bolo Board", withMessage: "Location service is disabled!!") 
      break 

     case .restricted: 
      print("Restricted.") 
      self.showAlertMessage(messageTitle: "Bolo Board", withMessage: "Location service is disabled!!") 
      break 

     case .denied: 
      print("Denied.") 
     } 
    } 
} 

func showAlertMessage(messageTitle: NSString, withMessage: NSString) ->Void { 
    let alertController = UIAlertController(title: messageTitle as String, message: withMessage as String, preferredStyle: .alert) 
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction!) in 

    } 
    alertController.addAction(cancelAction) 

    let OKAction = UIAlertAction(title: "Settings", style: .default) { (action:UIAlertAction!) in 
     if let url = URL(string: "App-Prefs:root=Privacy&path=LOCATION/com.company.AppName") { 
      if #available(iOS 10.0, *) { 
       UIApplication.shared.open(url, options: [:], completionHandler: nil) 
      } else { 
       // Fallback on earlier versions 
      } 
     } 
    } 
    alertController.addAction(OKAction) 
    self.present(alertController, animated: true, completion:nil) 
} 
0

私も同じ問題がありました。このコードを使用することができます。

func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) { 

    viewController.dismiss(animated: true, completion: nil) 
    let geoCoder = CLGeocoder() 
    let location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude) 
    geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in 

     // Place details 
     var placeMark: CLPlacemark! 
     placeMark = placemarks?[0] 

     // Address dictionary 
     print(placeMark.addressDictionary as Any) 
    // 

    print("Place name \(place.name)") 
    print("Place address \(String(describing: place.formattedAddress))") 
    print("Place attributions \(String(describing: place.attributions))") 



}) 
} 

ご希望の場合は、問題を解決してください。

関連する問題