Swift — как дождаться, пока GPS вернет правильные координаты

#swift #swiftui #core-location

#swift #swiftui #ядро-местоположение

Вопрос:

В настоящее время я сталкиваюсь с проблемой, когда GPS возвращает координаты 0,0, когда я вызываю местоположение при первом запуске. Если я снова вызову ту же функцию через секунду, она вернет правильные значения, поэтому я думаю, что мне просто нужно подождать получения координат, пока GPS не «прогреется», но я не уверен, как это сделать.

Это функция, которую я вызываю:

 func reload(){
        
        var coor = self.locationManager.location != nil ?
            self.locationManager.location!.coordinate :
            CLLocationCoordinate2D()

       //I send a http request using the gps data here
        ...
    }
}
 

Я вызываю эту функцию в .onapear для представления, и она извлекает правильные данные при отладке, но не при автономной работе. Я инициализирую диспетчер местоположений с помощью других переменных @state для представления.

Диспетчер местоположения:

 class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate
{
 
    
    @Published var location: CLLocation? = nil
    @Published var locationAllowed:Bool = true
    
    private let locationManager = CLLocationManager()
    
    override init() {
        super.init()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.distanceFilter = kCLDistanceFilterNone
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
    }

    ...
}
 

Это общая структура программы:

 struct ContentView: View {

    @ObservedObject private var locationManager = LocationManager()
    
    var body: some View {
         View{
         }.onAppear(){
               Reload()
         }
    }
 

Ответ №1:

Вы правы в том смысле, что вам нужно подождать, пока GPS «прогреется», но это произойдет в неопределенное время в будущем.

Вы пропустили довольно много кода в своем LocationManager , но, предположительно, у вас есть методы делегирования, которые обновляют ваше @Published свойство location .

Вероятно, вам следует прослушать изменения location , а затем reload() при необходимости вызвать (т. Е. Первый вызов).

Это может выглядеть примерно так:

 
struct ContentView: View {

    @ObservedObject private var locationManager = LocationManager()
    @State private var hasLoaded = false
    
    var body: some View {
         VStack {
            Text("Hello, world")
         }.onReceive(locationManager.$location) { newLocation in
            if let newLocation = newLocation {
                reload(location: newLocation.coordinate)
            }
         }
    }
    
    func reload(location: CLLocationCoordinate2D) {
        guard hasLoaded == false else {
            return
        }
        hasLoaded = true
        //http request here
    }
}