Неправильное расположение пользователя MKMapView при запуске или резюме - PullRequest
9 голосов
/ 09 февраля 2011

Когда я запускаю свое приложение заново или возобновляю работу через долгое время, MKMapView неверно определяет местоположение пользователя и показывает меня посреди моря.

Я использую следующий код:

self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
[mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];

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

Ответы [ 7 ]

21 голосов
/ 03 ноября 2011

Это ожидаемое поведение: местоположение пользователя не всегда отслеживается iPhone с помощью GPS (это потребляет много энергии).Поэтому, как только карта отображается, экземпляр MKMapView показывает последнюю «лучшую» позицию пользователя, которую он знает, а затем повышает точность, активируя отслеживание (это простой процесс, вам не нужно об этом заботиться).

Вы можете отслеживать, когда MKMapView обновляет местоположение пользователя на карте, применяя протокол MKMapViewDelegate .Просто внедрите:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation      {
    CLLocationAccuracy accuracy = userLocation.location.horizontalAccuracy;
    if (accuracy ......) {
    } 
}

(Больше информации из документации Apple здесь )

Код выше в моем примере проверяет точность позиции, отображаемой в данный моментmapView и реагирует соответственно.

[РЕДАКТИРОВАТЬ]
Если показ местоположения пользователя в середине моря сначала действительно беспокоит вас, вы можете скрыть местоположение пользователя, пока не получите местоположение, которое является достаточно точным / свежим.
Для этого сначала установите для свойства showsUserLocation MKMapView значение NO, пока не получите достаточно точное местоположение (благодаря предыдущему обратному вызову делегата), а затем установите для него YES.
Byделая это, вы будете избегать отображения местоположения, которое не является точным или слишком старым для отображения (в CLLocation есть свойство timestamp, чтобы проверить, является ли оно старым или нет)

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

4 голосов
/ 07 ноября 2011

При непосредственном использовании CLLocationManager вы обычно получаете кэшированное местоположение в первом обратном вызове.Обычно это хорошее место, хотя и старое.После этого вы быстро получаете дополнительные колбэки, дающие лучшее местоположение, используя Wi-Fi, сотовую вышку (если есть).Если вы запросили точность <1000 м, вы получите (через несколько секунд) триангуляцию GPS.</p>

Ни один из них не должен быть достаточно неточным, чтобы оказаться посреди океана.Я подозреваю, что эта строка кода:

self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;

обращается к координате, в то время как userLocation или location равно nil.Если userLocation или location равно нулю, это вернет 0 координат.Местоположение lat = 0, lon = 0 находится в Атлантическом океане, у побережья Африки.Вы можете добавить проверку location, чтобы убедиться, что она не равна нулю, прежде чем получить координату из нее, например:

if (self.mapView.userLocation.location) {
    self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
    [mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];           
}

Вы также захотите дождаться обратных вызовов к MKMapViewDelegate * 1016.* mapView:didUpdateUserLocation: чтобы узнать, когда доступно действительное местоположение.Ваша реализация didUpdateUserLocation: должна отбросить любое местоположение, которое имеет horizontalAccuracy <0, которое указывает на недопустимое местоположение. </p>

-(void)mapView:(MKMapView*)mapView didUpdateUserLocation:(MKUserLocation*)userLocation
{
    if (userLocation.location.horizontalAccuracy > 0) {
        [mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];           
    }
}
1 голос
/ 04 ноября 2011

То, что я делаю здесь, -

  1. начать обновление местоположения
  2. при обновлении местоположения, проверьте возраст местоположения, если оно слишком старое, я жду
  3. при получении нового обновления я обновляю его на карте

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

1 голос
/ 02 ноября 2011

Так же, как написал Джереми Массел, вы должны разобраться с первыми плохими позициями при запуске / продолжении приложения.Нашел отличный пост в блоге пару месяцев назад:

http://troybrant.net/blog/2010/02/detecting-bad-corelocation-data/

1 голос
/ 09 февраля 2011

Это, к сожалению, функция чипа GPS.Он не всегда включен, поэтому данные обычно будут неверными в первые пару мгновений.Лучше всего, вероятно, было бы сохранить последнюю позицию, записанную приложением в NSUserDefaults, затем дождаться, пока точность окажется там, где вы хотите, прежде чем переключаться на живые данные, или же скрыть MkMapView, пока точность не окажется там, где вы этого хотите.чтобы быть, затем отобразить его в тот момент (вы можете показать экран загрузки в промежуточный период)

0 голосов
/ 02 ноября 2011

В своих приложениях я использовал следующие методы:

Во-первых - хорошо иметь позицию по умолчанию (например, приложение касается города, затем увеличить масштаб, чтобы отобразить весь город) (при первом открытии первого приложения, когда данные не загружены)

Во-вторых - если пользователь уже использовал карту - может сохранить свои координаты и показать их (уровень + span (zoom)), если другие данные недоступны.

Третье - в случае данных:

1.) Если база данных уже имеет некоторые координаты - при первом открытии карты (когда приложение закрыто) - уменьшить / увеличить, чтобы показать все выводы на карте.

2.) Когда вы все еще на карте и только что получили обновления (новые местоположения или что-то изменили), есть две возможности:

2.1.) Если пользователь не увеличил масштаб до какого-либо местоположения - карта увеличивает или уменьшает масштаб, чтобы показать все местоположения.

2.2.) , если пользователь увеличил масштаб - местоположения обновляются, но карта не уменьшает

Конечно - тогда есть также несколько кнопок фильтров (например: поиск, местоположение пользователя и некоторые другие - которые фильтруют местоположения и уменьшают / уменьшают, чтобы показать отфильтрованные результаты)

0 голосов
/ 09 февраля 2011

Как далеко это от вашего фактического местоположения? Когда приложение только запускается или возобновляет работу в течение длительного периода времени, местоположение пользователя обычно всегда неверно. По мере запуска приложения оно будет становиться все более и более точным. В CLLocationManager есть методы получения точности местоположения пользователя, посмотрите, какие значения вы там получаете.

...