Как получить географические координаты и передать их в другой View Controller (Swift)
iOS-приложение имеет 2 View Controller. Первый получает координаты и отображает точку на карте (в файл info.plist нужная строчка добавлена):
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, CLLocationManagerDelegate {
let userDefMap = UserDefaults.standard
@IBOutlet weak var map: MKMapView!
@IBOutlet weak var latCoordLabelOnMap: UILabel!
@IBOutlet weak var lonCoordLabelOnMap: UILabel!
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.activityType = .fitness
locationManager?.startUpdatingLocation()
if let coordinate = locationManager?.location?.coordinate {
let xScale:CLLocationDegrees = 0.01
let yScale:CLLocationDegrees = 0.01
let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: yScale, longitudeDelta: xScale)
let region = MKCoordinateRegion(center: coordinate, span: span)
map.setRegion(region, animated: true)
}
map.userTrackingMode = .followWithHeading
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// метки на карте c координатами:
latCoordLabelOnMap.text = String( (locations[0].coordinate.latitude))
lonCoordLabelOnMap.text = String( (locations[0].coordinate.longitude))
self.userDefMap.setValue(locations[0].coordinate.latitude, forKey: "lat")
self.userDefMap.setValue(locations[0].coordinate.longitude, forKey: "lon")
}
override func viewDidDisappear(_ animated: Bool) {
locationManager?.stopUpdatingLocation()
}
}
Второй View Controller имеет в том числе 2 UILabel, на которых нужно отображать координаты - широту и долготу и обновлять их с некой частотой, которую можно задать с помощью переменной.
- Как правильно передавать координаты во второй View Controller?
- Как реализовать периодичность получения координат и обновления UILabels?
Нашел в сети несколько примеров с передачей данных между View Controllers, но адаптировать не получается.
Ответы (2 шт):
Описал два варианта. Вариант 1: работает через протокол, который уведомляет второй котроллер. Вариант 2: просто запрос к locationManager через переменную shared.
Если будут вопросы - Задавайте!
// Вариант 1: протокол для получения координат
protocol MapViewControllerDelegate: class {
func getCoordinate(lat: Double, lon: Double)
}
class MapViewController: UIViewController, CLLocationManagerDelegate {
let userDefMap = UserDefaults.standard
@IBOutlet weak var map: MKMapView!
@IBOutlet weak var latCoordLabelOnMap: UILabel!
@IBOutlet weak var lonCoordLabelOnMap: UILabel!
// статическая переменная класса дает доступ к классу
static var shared: MapViewController?
// Вариант 1: делегат используется для отправки данных по протоколу
var delegate: MapViewControllerDelegate?
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
// инициализируем shared
MapViewController.shared = self
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.activityType = .fitness
locationManager?.startUpdatingLocation()
if let coordinate = locationManager?.location?.coordinate {
let xScale: CLLocationDegrees = 0.01
let yScale: CLLocationDegrees = 0.01
let span: MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: yScale, longitudeDelta: xScale)
let region = MKCoordinateRegion(center: coordinate, span: span)
map.setRegion(region, animated: true)
}
map.userTrackingMode = .followWithHeading
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// метки на карте c координатами:
latCoordLabelOnMap.text = String((locations[0].coordinate.latitude))
lonCoordLabelOnMap.text = String((locations[0].coordinate.longitude))
// Вариант 1: отправка данных по протоколу
delegate?.getCoordinate(lat: locations[0].coordinate.latitude, lon: locations[0].coordinate.longitude)
}
override func viewDidDisappear(_ animated: Bool) {
locationManager?.stopUpdatingLocation()
}
// вариант 2: по запросу обращаемся к locationManager для получения координат
func getCoordinate() -> (lat: Double, lon: Double)? {
guard let coordinate = locationManager?.location?.coordinate else {
return nil
}
return (lat: coordinate.latitude, lon: coordinate.longitude)
}
}
class TwoViewController: UIViewController {
@IBOutlet weak var latCoordLabelOnMap: UILabel!
@IBOutlet weak var lonCoordLabelOnMap: UILabel!
override func viewDidLoad() {
// Вариант 1: указывает, что этот класс будет получать уведомления по протоколу
MapViewController.shared?.delegate = self
}
// вариант 2: запрашиваем координаты
@IBAction func getCoorginateAction() {
guard let coordinate = MapViewController.shared?.getCoordinate() else {
return
}
latCoordLabelOnMap.text = String(coordinate.lat)
lonCoordLabelOnMap.text = String(coordinate.lon)
}
}
extension TwoViewController: MapViewControllerDelegate {
// Вариант 1: получаем уведомление с делегата по протоколу
func getCoordinate(lat: Double, lon: Double) {
latCoordLabelOnMap.text = String(lat)
lonCoordLabelOnMap.text = String(lon)
}
}
Попробуйте этот вариант. Здесь два вью контроллера, второй контроллер получает данные в таймере каждую секунду.
class MapViewController: UIViewController, CLLocationManagerDelegate {
let userDefMap = UserDefaults.standard
@IBOutlet weak var map: MKMapView!
@IBOutlet weak var latCoordLabelOnMap: UILabel!
@IBOutlet weak var lonCoordLabelOnMap: UILabel!
// статическая переменная класса дает доступ к классу
static var shared: MapViewController?
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
// инициализируем shared
MapViewController.shared = self
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.activityType = .fitness
locationManager?.startUpdatingLocation()
if let coordinate = locationManager?.location?.coordinate {
let xScale: CLLocationDegrees = 0.01
let yScale: CLLocationDegrees = 0.01
let span: MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: yScale, longitudeDelta: xScale)
let region = MKCoordinateRegion(center: coordinate, span: span)
map.setRegion(region, animated: true)
}
map.userTrackingMode = .followWithHeading
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// метки на карте c координатами:
latCoordLabelOnMap.text = String((locations[0].coordinate.latitude))
lonCoordLabelOnMap.text = String((locations[0].coordinate.longitude))
}
override func viewDidDisappear(_ animated: Bool) {
locationManager?.stopUpdatingLocation()
}
// по запросу обращаемся к locationManager для получения координат
func getCoordinate() -> (lat: Double, lon: Double)? {
guard let coordinate = locationManager?.location?.coordinate else {
return nil
}
return (lat: coordinate.latitude, lon: coordinate.longitude)
}
}
class TwoViewController: UIViewController {
@IBOutlet weak var latCoordLabelOnMap: UILabel!
@IBOutlet weak var lonCoordLabelOnMap: UILabel!
override func viewDidLoad() {
// Timer будет работать через каждую секунду
let getCoordinateTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
// запрос на координаты из MapViewController
guard let coordinate = MapViewController.shared?.getCoordinate() else {
return
}
self.latCoordLabelOnMap.text = String(coordinate.lat)
self.lonCoordLabelOnMap.text = String(coordinate.lon)
}
// Запуск таймера
getCoordinateTimer.fire()
}
}