0

我正在尝试使用叠加层在 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
4

1 回答 1

0

首先,您试图在设置self之前调用设置器(即您的self.delegate = self之前 [super init...])。这在任何对象的任何地方都不起作用。

不过,更重要的是,delegate您打算设置哪个?您的UCRouteView类是 的子类MKOverlayView,它没有delegate属性(也没有它的超类)。实际上,您的方法来自<MKMapViewDelegate>,表明您打算设置mapView' 委托。所以正确的调用应该是[[self mapView] setDelegate:self](或者,如果你更喜欢点语法,self.mapView.delegate = self.

我还没有详细浏览您的其余代码......看看进行上述更改是否至少会导致您的方法被调用。(我不完全确定你的类架构在这里是最优的,但我们在这个阶段不需要处理这个问题。)

于 2012-05-15T00:57:46.370 回答