Получить местоположение пользователя работает только со второго раза - PullRequest
0 голосов
/ 09 января 2019

Первый: извините за плохой заголовок. Я не знаю, как лучше описать мою проблему.

У меня есть этот код в моем проекте Xcode:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()
    var currentLocation = "PLACEHOLDER"

    override func viewDidLoad() {
        self.locationManager.requestWhenInUseAuthorization()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        super.viewDidLoad()
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
        currentLocation = String(locValue.latitude)
    }
    @IBAction func sendLocation() {
        locationManager.startUpdatingLocation()
        print(currentLocation)
        locationManager.stopUpdatingLocation()
    }
}

Печатает местоположение пользователя при нажатии на кнопку UIB.

Это работает. Но по какой-то причине при первом нажатии кнопки UIB после перезапуска приложения печатается PLACEHOLDER вместо местоположения.

Означает: когда я запускаю приложение и нажимаю на UIButton три раза, я получаю это в консоли:

PLACEHOLDER
56.153666216328625
56.153666216328625

вместо этого:

56.153666216328625
56.153666216328625
56.153666216328625

Я также пытался сохранить как UserDefaults вместо var, но это приводит к той же проблеме.

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Обновления местоположения отправляются вам асинхронно, поэтому вы не можете распечатать currentLocation сразу после вызова startUpdatingLocation ().

Просто поместите отпечаток внутри делегата

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
    currentLocation = String(locValue.latitude)
    print(currentLocation) // print only after updating the location
}

и должно работать

0 голосов
/ 09 января 2019

Проблема в том, что обновления местоположения принимаются асинхронно, поэтому вы печатаете значение currentLocation до того, как новое обновление местоположения вызовет вызов делегата locationManager(_:, didUpdateLocations), и, следовательно, ваша переменная currentLocation будет напечатана до того, как она будет обновлено. Вам нужно напечатать значение внутри метода делегата, чтобы отобразить обновленное значение.

Кстати, если вы хотите получать одно обновление местоположения, вы не должны использовать startUpdatingLocation и stopUpdatingLocation сразу после друг друга, тем более что вы можете фактически прекратить обновление до того, как произойдет одно обновление из-за асинхронности. Вы должны использовать requestLocation для получения одноразового обновления местоположения. Более того, вы должны использовать переменную locations в вызове делегата, а не manager.location.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let coordinate = locations.last?.coordinate else { return }
    currentLocation = String(coordinate.latitude)
    print(currentLocation)
}

@IBAction func sendLocation() {
    locationManager.requestLocation()
}
...