Найдите название города и страну из широты и долготы в Свифте
Я работаю над приложением в Swift3
и у меня есть проблема с письмом, я не могу найти ответ.
Как узнать название города и названия коротких мест страны на широте и долготе?
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)
}
}
Ответы
Ответ 1
Я бы рекомендовал интегрировать API Карт Google в ваш проект. Если вы это сделаете, ваша задача может быть достигнута с помощью Reverse Geocoding, который предоставляет Google.
Кроме того, Google предлагает SDK Google Maps для разработки IOS, что также стоит рассмотреть.
UPD:. Это можно сделать без интеграции карт в ваш проект. Основываясь на этом, вы можете добиться этого, используя HTTP-запросы к API Google. Запрос:
https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY
возвращает объект JSON
с информацией о запрошенном месте, включая название страны и города.
Кстати, я настоятельно рекомендую использовать Alamofire, чтобы выполнить HTTP-запросы в Swift.
Ответ 2
Вы можете использовать метод CLGeocoder reverseGeocodeLocation, чтобы получить метку CLPlace и получить информацию о свойствах страны и местности. Обратите внимание, что это асинхронный метод, поэтому вам нужно будет добавить обработчик завершения к вашему методу при получении этой информации:
import UIKit
import MapKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func fetchCityAndCountry(from location: CLLocation, completion: @escaping (_ city: String?, _ country: String?, _ error: Error?) -> ()) {
CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
completion(placemarks?.first?.locality,
placemarks?.first?.country,
error)
}
}
использование
let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
fetchCityAndCountry(from: location) { city, country, error in
guard let city = city, let country = country, error == nil else { return }
print(city + ", " + country) // Rio de Janeiro, Brazil
}
Ответ 3
То, что вам нужно, называется обратным геокодированием. Поскольку вы уже объявили некоторые свойства в верхней части. Вам нужно добавить 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 view didLoad или из любого места, где вы хотите запустить диспетчер местоположений, сначала добавьте чек
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()
}
реализовать метод делегирования для менеджера местоположений didUpdateLocations
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 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 if for some reason location manager is nil
}
}
Вам нужно, чтобы cmd + щелкнуть по CLPlacemark, чтобы увидеть все свойства, к которым вы можете получить доступ, например, название улицы называется профайла, а номер называется subThoroughfare. документация для получения дополнительной информации
Примечание. Вы должны проверить ошибку местоположения и ошибку геокодера, которую я здесь не реализовал, но вы должны позаботиться об этих ошибках и лучше всего проверить коды ошибок, а все остальное - документация ящиков.
Обновить: проверить функцию paresPlacemarks, где я добавил isoCountryCode, который равен стране shortName. Не нужно добавлять дополнительные сетевые вызовы в google API и Alamofire, в то время как уже используемые службы определения местоположения
Ответ 4
Вот код Swift 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)
}
Ответ 5
Для этого вы можете использовать CLGeocoder
, из CoreLocation. Из документации Apple (подчеркивает мое):
Объект с одним выстрелом для преобразования географических координат и географических названий.
Класс CLGeocoder
предоставляет услуги для преобразования между координатой (заданной как широта и долгота) и удобным для пользователя представлением этой координаты. Удобное представление координаты обычно состоит из уличной, городской, состояния и страны информации, соответствующей данному местоположению...
Эта служба не связана с MapKit и, как таковая, не требует, чтобы вы использовали/показывали карту в своем приложении по адресу все.
Ответ 6
1 импортировать CoreLocation 2. вставьте CLLocationManagerDelegate в свой класс 3. Используйте методы делегирования, описанные ниже... надеюсь, это поможет вам найти название города и страну, выполнив следующие действия... Вот мой код
import UIKit
import CoreLocation
class MyViewController:UIViewController,CLLocationManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestAlwaysAuthorization()
self.locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if( CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways){
if let currentLocation = locationManager.location
{
if NetworkFunctions.NetworkRechability()
{
getAddressFromLatLon(pdblLatitude: "\(Double((currentLocation.coordinate.latitude)))", withLongitude: "\(Double((currentLocation.coordinate.longitude)))")
}
}
}
}
func getAddressFromLatLon(pdblLatitude: String, withLongitude pdblLongitude: String) {
var center : CLLocationCoordinate2D = CLLocationCoordinate2D()
let lat: Double = Double("\(pdblLatitude)")!
let lon: Double = Double("\(pdblLongitude)")!
let ceo: CLGeocoder = CLGeocoder()
center.latitude = lat
center.longitude = lon
let loc: CLLocation = CLLocation(latitude:center.latitude, longitude: center.longitude)
ceo.reverseGeocodeLocation(loc, completionHandler:
{(placemarks, error) in
if (error != nil)
{
}
if placemarks != nil
{
let pm = placemarks! as [CLPlacemark]
if pm.count > 0 {
let pm = placemarks![0]
print(pm.country ?? "")
print(pm.locality ?? "")
print(pm.subLocality ?? "")
print(pm.thoroughfare ?? "")
print(pm.postalCode ?? "")
print(pm.subThoroughfare ?? "")
var addressString : String = ""
if pm.subLocality != nil {
addressString = addressString + pm.subLocality! + ", "
}
if pm.thoroughfare != nil {
addressString = addressString + pm.thoroughfare! + ", "
}
if pm.locality != nil {
addressString = addressString + pm.locality! + ", "
if pm.country != nil {
addressString = addressString + pm.country! + ", "
//uuuuu
if(location_city != pm.locality!.trimmingCharacters(in: .whitespaces))
{
location_city=pm.locality!.trimmingCharacters(in: .whitespaces)
DispatchQueue.main.async{
self.GetBeeWatherDetails(district: pm.locality!, country: pm.country!)
}
}
}
}
if pm.postalCode != nil {
addressString = addressString + pm.postalCode! + " "
}
}
}
})
}
}
Ответ 7
У меня тоже была такая же проблема. Вы можете использовать этот код.
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))")
})
}
Надеюсь, это решит вашу проблему.
Ответ 8
Этот метод даст вам текущее местоположение, название города, название страны и т.д.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
// Process Response
if let error = error {
print("Unable to Reverse Geocode Location (\(error))")
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
self.city = placemark.locality!
//self.country = placemark.country!
}
}
}
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoomLevel)
self.locationv = CLLocation(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
if myView.isHidden {
myView.isHidden = false
myView.camera = camera
} else {
myView.animate(to: camera)
}
}
Ответ 9
Смотрите мой ответ в swift 4.1 Xcode 9.4.1. Вы можете получить даже детали названия деревни также. Получите название местоположения от Широты & Долготы в iOS