1

I am trying to display a lot of MKCircles using the MapKit. So far I have extended MKCircle <MKOverlay> in a class called Circle. I have a property that is readonly called circleView. In the getter I construct the MKCircleView.

-(MKCircleView *)circleView {
    if(!_circleView){
        _circleView = [[MKCircleView alloc] initWithOverlay:self];

        [_circleView setFillColor:self.color];
    }

    return _circleView;
}

Then, in the map, I do:

- (MKOverlayView *)mapView:(MKMapView *)mapView 
            viewForOverlay:(id<MKOverlay>)overlay {
   if ([overlay isKindOfClass:Circle.class]) {
       Circle *region = overlay;

       return [region circleView];
    }

    return nil;
}

I am loading those circles from a server, however I can have several circles (more than 1k displaying in a region).

I feel like the UI isn't responsive enough. Even with Circles in cache from the server it takes a while to redraw them and moving around the region can be painful. Is there any way to improve this performance?

EDIT

I have discovered that I was displaying more circles that necessary but still it is slow as hell.

Tiago Almeida
  • 14,081
  • 3
  • 67
  • 82
  • Why are you showing so many circles at one time, how does it benefit the user? – Wain Jul 12 '13 at 10:01
  • Imagine that you are organizing some cleaning campaign in your country. Everyone is responsable for some small area (10 meters). It is interesting to check, with some precision, what area was cleared. – Tiago Almeida Jul 12 '13 at 10:08
  • How about changing the display so when zoomed out you get highlights on the areas not covered and when you zoom in it switches to the areas that are covered. The aim being to present the information better and using less overlays. You can also do some profiling to prove it's the overlay count that causes the slowness. – Wain Jul 12 '13 at 10:12

1 Answers1

0

Not only will it affect the UI and drawing speed but plotting that much overlays on a map will cause memory problems on the actual device. This is due the NOT reusing of overlays by MapKit. As annotations have the reuseWithIdentifier, overlays however don't. Each overlay creates a new layer as a MKOverlayView on the map with the overlay in it. In that way memory-usage will rise quite fast and scrolling becomes... let's say sluggish to almost impossible.

Therefore there is a work-around: Instead of plotting each overlay individually, you can add all of the MKOverlays (in your case MKCircles) to one MKOverlayView. This way you're in fact creating only one MKOverlayView and thus there's no need to reuse.

The answer in this question contains a work-around.

I've used this approach in a way with multiple MKPolygons and it works great.

Community
  • 1
  • 1
wkberg
  • 391
  • 2
  • 12
  • thanks for your answer. I can't see the question in the apple forums. It sends me to an error page. How can I add MKOverlays to MKOverlayView? I have tried with "addView" method but it doesn't work :/. – Tiago Almeida Jul 16 '13 at 08:39
  • See my own answered question: [add multiple `MKOverlays` to one `MKOverlayView`](http://stackoverflow.com/questions/17673410/mkmapview-with-multiple-overlays-memory-issue/17673411#17673411) – wkberg Jul 16 '13 at 09:56
  • I am having some trouble adapting to MKCircle. Also, my problem is kinda different because I want to keep drawing circles while I am going to fetch them from the server (you presume that you have all your data and then you show it) – Tiago Almeida Jul 16 '13 at 18:00
  • Adapting to MKCircle is possible. Also, your other problem should be solvable too. Add them to the MultiOverlayView and then update it again on the map. You could do this in stages while fetching them from the server. The point is that having so many circles on the map causes memory-issues on actual-devices. ;-) – wkberg Jul 17 '13 at 18:02
  • You are jumping some steps on this process. What MultiOverlayView extends from? MKOverlayView? How can I draw the circles? How can I force an update on the MultiOverlayView? – Tiago Almeida Jul 21 '13 at 17:28
  • MultiOverlayView is a custom class of MKOverlayView. You can draw circles using your normal MKCircle method but the point is that this example is based on polygons. Polygons aren't the same as circles and therefore the MultiOverlayView class needs to be adjusted. The outcome will be the same, less memory usage. You can then just refresh the MultiOverlayView by deleting and adding it again to the map. I will try to post an solution with the adjusted MKCircle approach but the problem is time ;-) – wkberg Jul 31 '13 at 11:36
  • I have tried with a lot of approaches. Using yours but instead of drawing polygons I take the coordinates and draw a circle using CGContext, using bezierPathWith... etc. MultiOverlayView I have also tried it but not in the way you suggested. I have tried to extend it. The way I understood you know you are saying that I should add things to it. Am I right? This is way more confusing than I was expecting. – Tiago Almeida Jul 31 '13 at 17:39