为什么MKOverlayRenderer上的drawRect会变慢

时间:2014-09-09 17:40:28

标签: ios objective-c mkmapview core-graphics

对于应用程序,我必须在MKMapView上放置MKCircle注释。但是,需要移动/调整圆的大小。我知道有人问这个,例如Moving MKCircle in MKMapView建议删除/添加注释以获取该行为。

但是,我认为绘图非常慢,就像这篇文章中的用户一样:Smooth resizing of MKCircle。由于现在有这个问题的答案,问题似乎是使用YHAnimatedCircleView。我的意思是,当我使用UISlider来改变圆的半径时,重绘是草率的,我也可以注意到用于绘制它的瓷砖。

我创建了一个小测试代码,覆盖了子类MKOverlayRenderer的drawMapRect。代码如下:

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

当我移动UISlider时,旧的注释被移除,并且放置了具有不同半径的新MKCircle并调用drawMapRect方法。

然而,即使是这个小例子也会在调整圆圈大小时显示草率。

问题:

  1. 以上示例是完全正确还是我在绘图时出错?
  2. 如果示例是正确的,为什么重新调整圆圈时重绘它的速度太慢/马虎?

2 个答案:

答案 0 :(得分:0)

据我所知,MKMapView中的drawRect非常慢。 (作为好奇心的人,CCHMapClusterController also found out that

我要做的是生成UIImage而不是绘制rect 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();

您可以在AnnotationView中的layoutSubViews中生成该图像(很像链接显示:))。 AnnotationView可以具有半径,UISlider将改变半径。在您的setRadius属性中,您可以调用setNeedsLayout

答案 1 :(得分:0)

我在MKMapView上绘制叠加层时遇到了类似的问题,我的问题是移动了我绘制的与地图相关的圆圈。这导致了一个问题,即地图的移动与圆圈中的移动相比存在滞后,看起来好像圆圈在地图上滑动而不是固定在地图上。

我的解决方案是使用CADisplayLink来同步MKMapView的绘图和我添加到它的任何视图。我相信这可以使用UISlider改变圆的半径的原始实现,但是没有实现,我无法彻底测试它。

代码示例如下:

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

我希望这可以帮助您解决问题。