MKMapView charger toutes les vues d'annotation à la fois (y compris ceux qui sont en dehors du courant rect)

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

Question

UPDATE

On dirait que ce problème a été discrètement corrigé dans iOS 4.3. Jusqu'à ce point, la distance qui a été considéré comme « assez loin » pour une annotation à recycler semblait être des centaines de miles, même lorsque zoomé très près. Quand je construis mon application avec le SDK iOS 4.3, les annotations sont recyclées basées sur des limites plus raisonnables.


Quelqu'un at-il d'autre dans l'exécution de ce problème? Voici le code:

- (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;
    }

...

Dès que la vue est affichée, je reçois

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

et ainsi de suite, pour chaque annotation (~ 60) J'ai ajouté. La carte (correctement) affiche uniquement les deux annotations dans la rect actuelle. Je suis en train de la région 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];

L'entrée de journal pour la région étant ensemble est imprimé à la console avant que des vues d'annotation sont demandées.

Le problème ici est que, puisque toutes les annotations sont demandées à la fois, [Mapview dequeueReusableAnnotationViewWithIdentifier] ne fait rien, car il y a MKAnnotationViews uniques pour chaque annotation sur la carte. Cela conduit à des problèmes de mémoire pour moi.

Un problème possible est que ces annotations sont regroupées dans un espace assez petit (~ rayon de 1 mile). Bien que la carte est zoomée assez serré dans viewDidLoad (delta .001 latitude et longitude), il charge encore toutes les vues d'annotation à la fois.

Merci ...

Était-ce utile?

La solution

Qu'est-ce que vous attendez est une sorte de « coupure » des vues d'annotation sur la base actuelle region les écrans de carte.

Ce n'est pas la façon dont fonctionne le sélecteur de dequeueReusableAnnotationViewWithIdentifier.

De la documentation: En vue d'annotation se déplacent hors-champ , la vue de la carte les déplace vers une file d'attente de réutilisation gérée en interne. Alors que de nouvelles annotations à l'écran se déplacent, et votre code est invité à fournir une vue d'annotation correspondante, vous devez toujours essayer de dequeue une vue existante avant de créer un nouveau.

Ainsi, le mécanisme réutilisable n'a de sens que lorsque vous invoquez une séquence comme:

//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];

En vous cas, la façon dont je mettre en œuvre la coupure (pour afficher uniquement l'annotation pour la région en cours d'affichage) est la suivante:

  • Ajouter un délégué à votre Mapview et mettre en œuvre la méthode - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated pour s'informer quand la région a changé
  • itérer tous vos objets pour obtenir ceux qui correspondent à cette région
  • addAnnotations à votre carte uniquement pour les objets (vous pouvez mettre en œuvre une sorte de fusion entre les annotations précédemment affiché et le nouveau ou simplement redémarrer à partir de zéro, supprimer toutes les annotations et définissez les nouveaux

Bien sûr, lorsque l'utilisateur effectue un zoom sur un assez grand nombre et que la portée de la région est trop gros (trop de broches à afficher), alors vous devez prendre une décision: que je présente toutes les vues annotations (et prendre le risque que l'affichage sur la carte ne donne pas beaucoup d'information) ou dois-je définir un message à l'utilisateur en disant « Zoomez pour obtenir des broches » ou autre chose. Mais ceci est une autre histoire ...;)

Autres conseils

Je ne sais pas si cela va aider, mais vous avez mentionné les problèmes de mémoire en raison de la charge de 60 ~ objets. Est-il possible de charger conditionnellement chaque objet en fonction de la région centre de la carte actuelle et la durée actuelle de la région de carte?

//:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top