1

I've searched a bit around the web and found a few ideas on how to do what I want, but I would still like to know what you think I should do.

Here is the context :

I'm developing an app for iOS 5. I use MapKit to display a map, and I add around 5000 annotations to it - yup, that seems a lot, but don't worry, I use a clustering library :). In order not to load them every time the user opens the map, I create them in my appDelegate (I create an array of annotations, and call [_mapView addAnnotations:[appDelegate.annotationsToAdd allObjects]]; when I open the map). It takes about roughly 10 seconds to create the annotationsToAdd array, so I think this solution is working pretty well (you have to wait for those 10 seconds before being authorized to open the map, but you only wait once, at the launch of the app). In each of those annotations, I have a "link" to an object, which contains an array of values (15 floats). For now, when I create the annotation, the subtitle method returns one of those values.

In my map's ViewController, I have 2 segmented controls. The first one has 3 segments, the second one has 5, which gives 15 combinations - yup again, that's the same number of values the array of the object in my annotation has :).

So you may have seen my problem coming, I would like to update the subtitle of every annotation on my map (even the ones in the clusters, as the cluster gives an average value based on the pins it holds). What I would also want is to update the annotationView's color/image based on the value of the annotation's subtitle.

I may be wrong, but based on my research, I understand that you have to remove all the annotations, and recreate them all in order to do that. you understand that this is not an option in my case. I can't make the user wait 10 seconds every time he changes the value of one of the controls.

I saw an article on KVO: could that be a working solution ?

I don't know much about NSNotification, but should I use them ?

I would really appreciate your help, and I would even more appreciate a detailed answer, showing me the steps to follow in my apparently uncommon situation.

Thanks in advance.

rdurand
  • 7,342
  • 3
  • 39
  • 72
  • can you post the code of the container of the data and the code where you want to update the subtitle? it might help the SO community with context to craft an answer. e.g. is it necessary to change every one of the annotations at once? or could you live with changing them when they appear and you are able to read the annotations? (certainly, no one is able to read all 5000 annotations at any one time, even on an iPad Retina display, are they?) you might want to borrow from the theory Apple uses in iOS for TableView, where they only request data for table view cells that are visible. – john.k.doe Sep 30 '12 at 20:08

2 Answers2

4

First of all, you should just be adding the annotations all at once, not using a clustering library:

When configuring your map interface, you should add all of your annotation objects right away. The map view uses the coordinate data in each annotation object to determine when the corresponding annotation view needs to appear onscreen.

(From MKMapView Class Reference).

MKMapView will manage them for you so your app doesn't slow down. This approach will probably not be any slower than what you're doing, and then you could theoretically do:

[mapView removeAnnotations:mapView.annotations];
//add your annotations here

if you wanted to remove all of them and then add them all back.

However, you're incorrect that you have to remove them all at once. If you know of a specific annotation, you can simply do:

[mapView removeAnnotation:someAnnotation];
[mapView addAnnotation:someOtherAnnotation];

If you have the replacements in an NSArray, you can even:

[mapView removeAnnotations:arrayOfOldAnnotations];
[mapView addAnnotations:arrayOfNewAnnotations];

Finally, if you'd like to modify an annotation, you can do it using KVO (see this Stack Overflow question), but it's just as easy to remove, then add one, and the user won't notice as long as you aren't animating the add.

Community
  • 1
  • 1
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Hi. I do add all the annotations at once, the clustering library just regroups the annotation views displayed. I did not mean that I *can't* remove/add a single annotation, I meant that as *all* my annotations change at once, I think I *have* to remove all the views and add them back. Anyways, I'll consider using KVO (as I said in my comment in Stanislaw's answer, I did not know I could do that at the time), but the solution of iterating through the annotations as Stanislaw suggested may be better for my situation. Thanks for the answer. – rdurand Oct 01 '12 at 08:18
2

I am sorry if I haven't finally understood your situation quite well, but I feel like I am moving towards solving a similar problem so I'll try to share my thoughts with you. I will use your words as the guides for my response:

"you have to wait for those 10 seconds before being authorized to open the map"

Do you know about the following <MKOverlayView> protocol methods (see http://developer.apple.com/library/IOs/#documentation/MapKit/Reference/MKOverlayView_class/Reference/Reference.html):

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale

(Assuming that you have 5000 pins on entire world map, not on every fx 1km, i.e. not SO LARGE amount of pins) You can split your five thousands into the portions, so each portion of pins is to be populated by the corresponding MKMapRect region which is being drawn on the map. So your map is populated with pins/annotations, by demand, only for particular region at any given time. Depending on your situation this could bring a huge speed up.

This is a very good demonstration of working with MKMapRect tiles: https://github.com/mtigas/iOS-MapLayerDemo - populate with information only particular pieces of map. Also you may google something like "Map tiles 256px" to understand how the maps are being drawn.

"I understand that you have to remove all the annotations, and recreate them all in order to do that."

Why recreate? You do have an access to all the annotations that are already there on your map - why not just iterate through your associated annotations classes and update theirs subtitles?

Something like:

I hope that my points do address the scope of your question/situation.

Community
  • 1
  • 1
Stanislav Pankevich
  • 11,044
  • 8
  • 69
  • 129
  • No need to figure out when the annotations appear - just add them all at once, as described in the documentation: http://developer.apple.com/library/ios/#Documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html – Aaron Brager Oct 01 '12 at 00:08
  • Hi. Thanks for the answer. Unfortunately, the 5000 pins are not on the entire world map, but localized on only 2 cities... Since I asked my question, I saw that I may be able to use KVO (as Aaron also suggested in his answer) to update my annotation views. I'll look into that. Thanks again. – rdurand Oct 01 '12 at 08:11