在MKMapView上绘制/理解MKOverlayView的大问题

时间:2012-05-15 00:39:44

标签: iphone ios map overlay

我正在尝试使用叠加层在MKMapView上绘制路线。这是我的代码:

创建视图(按下按钮时调用):

NSArray *route = [UCGeoConverter generateCoordinatesFromKML:self.kmlResponse];
    if (!self.routeView) {
        NSLog(@"create route");
        self.routeView = [[UCRouteView alloc] initWithRoute:route mapView:self.mapview];
        [self.mapview addOverlay:self.routeView];
    }

现在这是我的UCRouteView.h文件。它继承自MKOverlayView并实现MKOverlay。

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "UCLocation.h"

@interface UCRouteView : MKOverlayView <MKOverlay>
{
    MKMapView* _mapView;
    NSArray* _points;
    UIColor* _lineColor;
}

-(id) initWithRoute:(NSArray*)routePoints mapView:(MKMapView*)mapView;

@property (strong, nonatomic) id delegate;
@property (nonatomic) MKCoordinateRegion region;
@property (nonatomic, retain) NSArray* points;
@property (nonatomic, retain) MKMapView* mapView;
@property (nonatomic, retain) UIColor* lineColor;
@end

现在实施。在这里,我有很大的麻烦。首先,似乎委托不起作用,因为没有方法被调用(除了init ..显然)我将委托设置为self。我很难理解它是如何工作的,所以如果你们能在这里帮助我,我将不胜感激,这一点非常重要!非常感谢

#import "UCRouteView.h"

@implementation UCRouteView

@synthesize mapView     = _mapView;
@synthesize points      = _points;
@synthesize lineColor   = _lineColor; 
@synthesize delegate    = _delegate;
@synthesize region      = _region;

-(id) initWithRoute:(NSArray*)routePoints mapView:(MKMapView*)mapView
{
    self.delegate = self;
    self = [super initWithFrame:CGRectMake(0, 0, mapView.frame.size.width, mapView.frame.size.height)];

    [self setMapView:mapView];
    [self setPoints:routePoints];

    // determine the extents of the route points and zoom to that area. 
    CLLocationDegrees maxLat = -90;
    CLLocationDegrees maxLon = -180;
    CLLocationDegrees minLat = 90;
    CLLocationDegrees minLon = 180;

    for(int idx = 0; idx < self.points.count; idx++)
    {
        UCLocation* currentLocation = [self.points objectAtIndex:idx];
        if(currentLocation.coordinates.latitude > maxLat)
            maxLat = currentLocation.coordinates.latitude;
        if(currentLocation.coordinates.latitude < minLat)
            minLat = currentLocation.coordinates.latitude;
        if(currentLocation.coordinates.longitude > maxLon)
            maxLon = currentLocation.coordinates.longitude;
        if(currentLocation.coordinates.longitude < minLon)
            minLon = currentLocation.coordinates.longitude;
    }

    _region.center.latitude     = (maxLat + minLat) / 2;
    _region.center.longitude    = (maxLon + minLon) / 2;
    _region.span.latitudeDelta  = maxLat - minLat;
    _region.span.longitudeDelta = maxLon - minLon;

    [self.mapView setRegion:_region];
    return self;
}
- (MKMapRect)boundingMapRect
{
    // 1. Problem: this returns the MapRect where the overlay is in, right? 
    // So why not just return the MapRect which is visible right now?
    return self.mapView.visibleMapRect;
}

-(BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale
{
   // 2. just return YES to make sure it draws
    return YES;
}

-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
    // 3. this never gets called? what's wrong?
    NSLog(@"mapview viewForOverlay");
    return self;
}

-(void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{    
    // does not get called either. I know the drawing code as is works to draw a route,
    // but I think I'm missing something here aswell..
    NSLog(@"draw route");
    // only draw lines if not in the middle of a transition and we 
    // acutally have some points to draw. 
    if(self.points && self.points.count > 0)
    {
        // set the color to draw the route
        if(nil == self.lineColor)
            self.lineColor = [UIColor blueColor];

        CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
        CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);

        // Draw them with a 2.0 stroke width
        CGContextSetLineWidth(context, 2.0);

        for(int idx = 0; idx < self.points.count; idx++)
        {
            UCLocation* location = [self.points objectAtIndex:idx];
            CGPoint point = [_mapView convertCoordinate:location.coordinates toPointToView:self];

            // set starting point and 'move' to it
            if(idx == 0)
            {
                // TODO: set special annotation for start/endpoint
                CGContextMoveToPoint(context, point.x, point.y);
            }
            else
            {
                CGContextAddLineToPoint(context, point.x, point.y);
            }
        }
        CGContextStrokePath(context);
    }
}
    @end

1 个答案:

答案 0 :(得分:0)

首先,您尝试在设置self之前调用设置器(即self.delegate = self [super init...]之前的<{1}}。这在任何对象中都不起作用。

但更重要的是,您打算设置哪个delegate?您的UCRouteView类是MKOverlayView的子类,它没有delegate属性(也没有超类)。实际上,您的方法来自<MKMapViewDelegate>,建议您打算设置mapView的委托。因此,正确的调用将是[[self mapView] setDelegate:self](或者,如果您更喜欢点语法,self.mapView.delegate = self

我还没有详细介绍其余的代码......看看上述更改是否至少会导致调用您的方法。 (我不完全确定你的班级架构在这里是最优的,但我们现阶段不需要处理它。)