Обработка большого количества аннотаций MKMapView
У меня есть представление карты с большим количеством аннотаций (3000+), когда пользователь масштабируется до разумного уровня, все хорошо и быстро.
Хотя, когда пользователь масштабируется и появляется большой quanitiy аннотаций, происходит много замедления из-за того, что сразу отображается количество аннотаций. Каков наилучший способ справиться с этим?
Текущее решение, которое я использую:
- (void)mapView:(MKMapView *)_mapView regionDidChangeAnimated:(BOOL)animated {
NSArray *annotations = [_mapView annotations];
MapAnnotation *annotation = nil;
for (int i=0; i<[annotations count]; i++)
{
annotation = (MapAnnotation*)[annotations objectAtIndex:i];
if (_mapView.region.span.latitudeDelta > .010)
{
[[_mapView viewForAnnotation:annotation] setHidden:YES];
warningLabel.hidden = NO;
}
else {
[[_mapView viewForAnnotation:annotation] setHidden:NO];
warningLabel.hidden = YES;
}
}
}
Отлично работает, хотя из-за большого размера цикла это приводит к значительному замедлению при масштабировании и выводе и прокрутке. Кажется, я не думаю о более эффективном способе справиться с этим, есть ли способ только прокрутить отображаемые в настоящее время аннотации или что-то по этим линиям, чтобы уменьшить размер цикла?
Ответы
Ответ 1
Как я понимаю ваш код, вы скрываете все представления аннотаций, если mapView увеличен более чем на определенное заданное значение.
Мне кажется, что было бы лучше, чем следующее:
- (void)mapView: (MKMapView*)_mapView regionDidChangeAnimated: (BOOL)animated
{
if (_mapView.region.span.latitudeDelta > .010 && self.mapViewsHidden == NO) {
for (MapAnnotation* annotation in _mapView.annotations) {
[[_mapView viewForAnnotation: annotation] setHidden: YES];
}
[self.warningLabel setHidden: NO];
[self setMapViewsHidden: YES];
}
else if (_mapView.region.span.latitudeDelta <= .010 && self.mapViewsHidden == YES) {
for (MapAnnotation* annotation in _mapView.annotations) {
[[_mapView viewForAnnotation: annotation] setHidden: NO];
}
[self.warningLabel setHidden: YES];
[self setMapViewsHidden: NO];
}
}
С приведенным выше, в большинстве случаев единственное, что делает этот код, это пара проверок.
Другим решением было бы удалить аннотации, если они не должны отображаться на карте. Лично я считаю, что это было бы лучше, так что коду не нужно создавать представления для аннотаций, которые еще не были показаны на карте.
Ответ 2
Я бы предложил пару вещей. Один, посмотрите на метод annotationsInMapRect:
. Согласно документам, в нем говорится:
Этот метод предлагает быстрый способ извлечения объектов аннотации в определенной части карты. Этот метод намного быстрее, чем выполнить линейный поиск объектов в свойстве аннотаций.
Два, посмотрите dequeueReusableAnnotationViewWithIdentifier:
. Согласно документам снова, в нем говорится:
По соображениям производительности вы обычно должны повторно использовать объекты MKAnnotationView в своих представлениях на карте. Поскольку представления аннотаций перемещаются за кадром, представление карты перемещает их в очередь повторного использования внутри организации. По мере того, как новые аннотации перемещаются на экране, а вашему коду предлагается предоставить соответствующий аннотационный вид, вы всегда должны пытаться удалить существующий вид перед созданием нового. Dequeueing экономит время и память во время критически важных операций, таких как прокрутка.
Наконец, пара мыслей. Вместо того, чтобы делать эти изменения каждый раз, когда вызывается метод - (void)mapView:(MKMapView *)_mapView regionDidChangeAnimated:(BOOL)animated
, как насчет того, чтобы делать это в соответствии с каким-либо другим правилом (например, после запуска таймера [убедитесь, что reset таймер при каждом вызове])? Другое дело: как объединить аннотации, которые очень близки друг к другу? Скажем, вы уменьшились до того места, где Род-Айленд выглядит очень маленьким, может быть, всего в десятке пикселей в ширину, и у вас есть 100 очков в Род-Айленде - вы должны просто отобразить один вывод.
Надеюсь, это поможет!
Ответ 3
В итоге я группировал свои аннотации в кластерах, используя OCMapView. Его бесплатный и очень простой в использовании в существующий код.
Он автоматически группирует ваши аннотации при уменьшении масштаба, и по мере того как вы увеличиваете масштаб изображения, они выглядят нечеткими, как они должны.
Я знаю, что это старый вопрос, но это отличный вариант для всех, кто пытается сделать то же самое.