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
didFindLocation
tofalse
когда вы называетеstartUpdatingLocation
. - внутри делегата перезвоните
didUpdateLocations:
, еслиdidFindLocation
былfalse
, setdidFindLocation
totrue
и затем вызов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
.