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

UPDATE

Похоже, эта проблема была тихо исправлена ​​в 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 (широта и долгота delta.001), она по-прежнему загружает все аннотации сразу.

Спасибо...

Ответы

Ответ 1

Что вы ожидаете, это своего рода "отсечение" представлений аннотаций, основанных на текущей области . Отображается карта.

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

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

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


// это создаст 1000 аннотаций
[theMap addAnnotations: my1000annotations];
// это будет перемещать их за кадром (но некоторые аннотации могут сохраняться внутри для дальнейшего повторного использования)
[theMap removeAnnotatios: theMap.annotations];
// добавив обратно некоторые аннотации на экран, некоторые из предыдущих представлений аннотаций будут повторно использоваться.
[theMap addAnnotations: someNew400annotations];

В этом случае способ, которым я выполнял бы отсечение (для отображения только аннотации для текущего отображаемого региона), является:

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

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

Ответ 2

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

//:)