locationManager didUpdateLocations срабатывает дважды на устройстве, только один раз на симуляторе
тот же код, я предполагаю, что устройство фактически обновляет местоположение дважды по какой-то причине, хотя я только вызываю startUpdatingLocation() один раз, и я запускаю некоторые stopUpdatingLocations() внутри didUpdateLocations
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
let loc: CLLocation = locations[locations.count - 1]
let id = 0
let type = 0
let number = 0
createNewDataPoint(id, loc: loc, type: type, number: number)
}
в этом случае createNewDataPoint вызывается дважды, создавая 2 новые точки данных. Это происходит только один раз в симуляторе, поэтому я предполагаю, что это имеет какое-то отношение к фактическому устройству и GPS, так как симулятор подделывает его местоположение.
startUpdatingLocation () только в моем коде один раз, на кнопке. В принципе, вы нажимаете кнопку, go go manager.startUpdatingLocations (), didupdatelocations попадает один раз на симулятор, два раза на устройство (идентичные координаты), и он создает 2 новые точки данных.
единственный другой код, который упоминает что-либо связанное, - это установка точности, фильтра, запросов авторизации и ранее упомянутого startUpdatingLocation(). Есть ли что-то, что я могу сделать? убедитесь, что я не создаю вдвое больше точек данных, чем необходимо?
8 ответов
методы делегата диспетчера местоположений могут вызываться очень часто и в любое время.
вы можете, однако, применить следующий алгоритм, чтобы защитить себя:
- создать глобальный
boolсказатьdidFindLocation. - Set
didFindLocationtofalseкогда вы называетеstartUpdatingLocation. - внутри делегата перезвоните
didUpdateLocations:, еслиdidFindLocationбылfalse, setdidFindLocationtotrueи затем вызовstopUpdatingLocation.
надеюсь, что это помогает.
лучший способ-сделать следующее:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
manager.delegate = nil
}
лучшее решение для iOS 10.0+
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
[locationManager stopUpdatingLocation]; // stop location manager
locationManager.delegate = nil;
//Your logics...
//This will be called only one time now.
}
но не забудьте снова установить делегата.
вы не получите часто на тренажере. и на устройстве, когда вы будете двигаться далеко, тогда только вы получите didUpdateLocations. просто двигайтесь в открытом пространстве, чтобы GPS мог определить ваше местоположение устройства, чтобы получить максимальную точность.
вместо запуска / завершения обновления местоположения и установки делегата на ноль существует метод requestLocation который идеально подходит, когда ваше приложение нужно быстро исправить местоположение пользователя:
документы:
override func viewDidLoad() {
// Create a location manager object
self.locationManager = CLLocationManager()
// Set the delegate
self.locationManager.delegate = self
}
func getQuickLocationUpdate() {
// Request location authorization
self.locationManager.requestWhenInUseAuthorization()
// Request a location update
self.locationManager.requestLocation()
// Note: requestLocation may timeout and produce an error if authorization has not yet been granted by the user
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Process the received location update
}
используйте этот метод, если требуется текущее местоположение пользователя, но не нужно оставлять службы location services запущенными.
решение@Zumry Mohamed является правильным
Я пробую код следующим образом:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
self.locationManager = nil;
}
наконец этот делегат вызывается только один раз, теперь я понимаю, почему возникла проблема, просто потому, что менеджер вызывает stopUpdatingLocationметод, но система не помогает нам сделать делегат недействительным, поэтому мы можем получать обратный вызов каждый раз при обновлении местоположения из-за вашего desiredAccuracy и distanceFilter настройки свойства CLLocationManager, поэтому окончательное решение так же, как сказал @Zumry Mohamed, мы можем вручную установить делегат в ноль, когда мы stopUpdateLocation. надеюсь, это поможет вам понять, что происходит, почему это может решить проблему.
locationManager.startUpdatingLocation () непрерывно извлекает местоположение и несколько раз вызывает метод didUpdateLocations, Просто установите значение для locationManager.значение distanceFilter перед вызовом locationManager.startUpdatingLocation().
по мере того как я установил 200 метров(вы можете изменить как ваше требование) работая отлично
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 200
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
после получения желаемой широты и долготы просто позвонить stopUpdatingLocation()и установить делегат nil.
В Swift 3:
locationManager.stopUpdatingLocation()
locationManager.delegate = nil
В Objective-C:
[locationManager stopUpdatingLocation]
locationManager.delegate = nil
здесь locationManager объект CLLocationManager.