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

StackOverflow https://stackoverflow.com/questions/1262742

Вопрос

Обновить

Похоже, что эта проблема была незаметно исправлена в iOS 4.3.До этого момента расстояние, которое считалось "достаточным" для переработки аннотации, казалось, составляло сотни миль, даже при очень близком увеличении.Когда я создаю свое приложение с помощью iOS 4.3 SDK, аннотации перерабатываются на основе более разумных ограничений.


Кто-нибудь еще сталкивался с этой проблемой?Вот код:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(WWMapAnnotation *)annotation {



// Only return an Annotation view for the placemarks. Ignore for the current location--the iPhone SDK will place a blue ball there.

NSLog(@"Request for annotation view");

if ([annotation isKindOfClass:[WWMapAnnotation class]]){



    MKPinAnnotationView *browse_map_annot_view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"BrowseMapAnnot"];



    if (!browse_map_annot_view) {
        browse_map_annot_view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"BrowseMapAnnot"] autorelease];
        NSLog(@"Creating new annotation view");
    } else {
        NSLog(@"Recycling annotation view");
        browse_map_annot_view.annotation = annotation;
    }

...

Как только вид отображается, я получаю

2009-08-05 13:12:03.332 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view

и так далее, для каждой аннотации (~ 60), которую я добавил.Карта (корректно) отображает только две аннотации в текущем прямоугольнике.Я устанавливаю регион в viewDidLoad:

if (center_point.latitude == 0) {
    center_point.latitude = 35.785098;
    center_point.longitude = -78.669899;
}

if (map_span.latitudeDelta == 0) {
    map_span.latitudeDelta = .001;
    map_span.longitudeDelta = .001;
}

map_region.center = center_point;
map_region.span = map_span;

NSLog(@"Setting initial map center and region");

[browse_map_view setRegion:map_region animated:NO];

Запись журнала для заданного региона выводится на консоль до того, как будут запрошены какие-либо просмотры аннотаций.

Проблема здесь в том, что, поскольку запрашиваются все аннотации одновременно, [MapView dequeueReusableAnnotationViewWithIdentifier] ничего не делает, поскольку для каждой аннотации на карте существуют уникальные MKAnnotationViews.Это приводит к проблемам с памятью у меня.

Одна из возможных проблем заключается в том, что эти аннотации сгруппированы на довольно небольшом пространстве (радиус ~ 1 миля).Хотя карта увеличена довольно сильно в viewDidLoad (дельта широты и долготы .001), она по-прежнему загружает все виды аннотаций одновременно.

Спасибо...

Это было полезно?

Решение

То, что вы могли бы ожидать, - это своего рода "обрезка" представлений аннотаций на основе текущего region отобразится карта.

Это НЕ тот способ, которым dequeueReusableAnnotationViewWithIdentifier селектор работает.

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

Таким образом, механизм повторного использования имеет смысл только тогда, когда вы вызываете последовательность, подобную :

//this will create 1000 annotation views
[theMap addAnnotations:my1000annotations];
//this will move them offscreen (but some annotation views may be kept internally for further reuse)
[theMap removeAnnotatios:theMap.annotations];
//when adding back again some annotations onscreen, some of the previous annotation views will be reused.
[theMap addAnnotations:someNew400annotations];

В вашем случае я бы реализовал отсечение (для отображения только аннотации для текущей отображаемой области) следующим образом :

  • Добавьте делегат в свой MapView и реализуйте - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated способ получения информации об изменении региона
  • выполните итерацию по всем вашим объектам, чтобы получить те, которые соответствуют этому региону
  • Добавьте примечания к вашей карте только для этих объектов (вы можете реализовать своего рода объединение ранее отображенных примечаний с новыми или просто перезапустить с нуля, удалить все примечания и установить новые

Конечно, когда пользователь сильно увеличивает масштаб изображения и область действия региона слишком велика (слишком много пинов для отображения), тогда вам нужно принять решение :показываю ли я все виды аннотаций (и рискую, что отображение на карте не дает много информации), или я отправляю пользователю сообщение с надписью "увеличить, чтобы получить пины" или что-то еще.Но это уже совсем другая история...;)

Другие советы

Не уверен, поможет ли это, но вы упомянули проблемы с памятью из-за загрузки ~ 60 объектов.Есть ли способ условно загружать каждый объект на основе текущего центра региона карты и текущего диапазона региона карты?

// :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top