Минимизируйте HTTP-запросы к моему серверу при использовании LocationManager - PullRequest
0 голосов
/ 23 декабря 2018

В приведенном ниже коде я использую LocationManager, чтобы получить текущий zipCode пользователя, а затем делаю HTTP-запрос на свой собственный сервер, чтобы получить некоторые данные, основанные на zipCode пользователя.Моя проблема в том, что мой код ниже делает HTTP-запрос каждый раз, когда вызывается locationManager, обычно три раза за вызов.В идеале я хотел бы сделать HTTP-запрос только после того, как будет найдена последняя метка.

Как можно минимизировать HTTP-запросы, направленные на мой собственный сервер?

override func viewDidLoad() {
    super.viewDidLoad()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)-> Void in
        if error != nil {
            //AlertView to show the ERROR message
        }
        if placemarks!.count > 0 {
            let placemark = placemarks![0]
            var zipCode = placemark.postalCode ?? ""
            makeHTTPRequest(zipCode) // this is called 3 times
            self.locationManager.stopUpdatingLocation()

        }else{
            print("No placemarks found.")
        }
    })
}

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Проблема в том, что ваш метод CLGeocoder возвращает асинхронно, и к тому времени, когда он возвращает значение, ваш менеджер местоположения уже срабатывал несколько раз.Поэтому просто прекратите обновлять местоположения после первого вызова менеджера местоположений, а затем выполните асинхронную работу.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    guard let location = locations.last else {
        return
    }

    // handle async work
    CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

        if let error = error {
            // alert with error
        } else if let placemarks = placemarks,
            placemarks.count > 0 {
            let placemark = placemarks[0]
            var zipCode = placemark.postalCode ?? ""
            makeHTTPRequest(zipCode)
        } else {
            print("No placemarks found.")
        }

    })

    locationManager.stopUpdatingLocation() // stop updating

}

Кстати, это также хорошая практика - связывать ваши операторы if-else.Если вы ведете с if, вы почти всегда должны следовать за ним с else вместо того, чтобы следовать с новым if блоком.

0 голосов
/ 23 декабря 2018

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

  • Определите глобальную переменную var didFindZipCode: Bool = false.
  • Добавьте guard didFindZipCode == false else { return } в начале блока if, в котором вы проверяете количество меток.
  • Установите didFindZipCode = true сразу после защитного заявления.

Просто не забудьте установить didFindZipCode на false всякий раз, когда вы захотите начать обновление местоположения снова.

...