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 объектов. Есть ли способ условно загрузить каждый объект на основе текущего региона области карты и текущего диапазона области карты?
//:)