2

For an app, I have to place a MKCircle annotation on a MKMapView. However, the circle needs to be moved/resized. I know this has been asked, e.g. Moving MKCircle in MKMapView where removing/adding the annotation is suggested to get that behavior.

However, I consider the drawing being very slow, like the user in this post: Smooth resizing of MKCircle. Since there are now answers to this question, the question seemed to use YHAnimatedCircleView. By slow I mean, when I use a UISlider to change the radius of the circle, the redrawing is sloppy and I can also notice the tiles being used to draw it.

I created a small test code, overriding drawMapRect of a subclasses MKOverlayRenderer. The code is as follows:

-(void) drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context
{
    MKCircle* circleOverlay = (MKCircle*)self.overlay;

    CLLocationCoordinate2D point = circleOverlay.coordinate;          

    CGPoint locationPoint =
        [self pointForMapPoint:MKMapPointForCoordinate(point)];

    CGFloat radius =
        MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) *
        circleOverlay.radius;

    CGRect circleRect = CGRectMake(locationPoint.x - radius,
                                   locationPoint.y - radius,
                                   radius * 2.0, radius * 2.0);

    CGContextSaveGState(context);    

    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillEllipseInRect(context, circleRect);

    CGContextRestoreGState(context);
}

When I move the UISlider the old annotation is removed and the new MKCircle with different radius is placed and the drawMapRect method gets called.

However, even this small example shows sloppy drawing when resizing the circle.

Questions:

  1. Is the above example entirely correct or am I doing something wrong with drawing?
  2. If the example is correct, why is the redrawing of the circle when resizing it so slow/sloppy?
Community
  • 1
  • 1
Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • Hi @SebastianDressler , did you managed to fix that problem? I'm struggling with it right know, i've tried everything but nothing seems to work... – bevoy Dec 10 '14 at 10:06
  • No, I never did. AFAIK there is only YHAnimatedCircleView which you could take as reference, but I don't like it for some reason. My solution was to color the pins I used differently. – Sebastian Dec 10 '14 at 10:42

2 Answers2

0

As far as I know drawRect in a MKMapView is extremely slow. (As a curiosity people that made CCHMapClusterController also found out that)

What I would do is generate an UIImage instead of doing draw rect:

UIImage *circle;

CGRect circleRect = CGRectMake(locationPoint.x - radius,
                               locationPoint.y - radius,
                               radius * 2.0, radius * 2.0);

UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius * 2.0, radius * 2.0), NO, 0.0f);

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);



CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
CGContextFillEllipseInRect(context, circleRect);

CGContextRestoreGState(ctx); 
  circle = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

You can generate that image in layoutSubViews in an AnnotationView (much like the link shows :)). That AnnotationView could have a radius and the UISlider would change the radius. In your setRadius property you call setNeedsLayout.

Tiago Almeida
  • 14,081
  • 3
  • 67
  • 82
0

I had a similar issue with drawing an overlay on an MKMapView, my issue was moving the circle I had drawn in relation to the map. This was causing a issue with there being lag in the movement of the map compared to the movement in the circle, looking as though the circle was gliding on top of the map as opposed to being fixed on the map.

My solution was to use a CADisplayLink in order to synchronise the drawing of the MKMapView and any views I had added to it. I believe this would work with your original implementation of changing the radius of the circle using a UISlider, however without the implementation, I can't thoroughly test this.

A code example is like this:

- (void)viewDidLoad {
    self.mapUpdateLink = [CADisplayLink displayLinkWithTarget:self
                                                 selector:@selector(updateMapView)];
    [self.mapUpdateLink addToRunLoop:[NSRunLoop mainRunLoop]
                             forMode:NSRunLoopCommonModes];
}

- (void)updateMapView {
    CGPoint centerPoint = [self.mapView convertCoordinate:self.circleView.centerCoordinate
                                            toPointToView:self.view];
    if (!isnan(centerPoint.x) && !isnan(centerPoint.y)) {
        self.circleView.center = centerPoint;
    }
}

I hope this helps you with your issue.

Elliott Minns
  • 2,774
  • 1
  • 17
  • 17