MKOverlayRenderer не отображает

У меня проблемы с отображением MKPolygonRenderer на моей карте. У меня есть класс MapViewController, содержащий MKMapView, и я создаю CustomMapOverlay экземпляры для рендеринга поверх MKMapView.

MapViewController.m:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.mapView.delegate = self;
    self.mapView.showsUserLocation = YES;
}

// ...

// Later, I retrieve some models and generate CustomMapOverlay instances from them...
for (Model *model in models) {
    CustomMapOverlay *customMapOverlay = [[CustomMapOverlay alloc] initWithModel:model];
    [self.mapView addOverlay:customMapOverlay];
}

// ...

// Implement MKMapViewDelegate protocol
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    MKPolygonRenderer *polygonRenderer = [[MKPolygonRenderer alloc] initWithOverlay:overlay];
    polygonRenderer.lineWidth = 2;
    polygonRenderer.strokeColor = [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:1.0];
    polygonRenderer.fillColor = [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:0.5];
    return polygonRenderer;
}

CustomMapOverlay.m:

@implementation CustomMapOverlay

// Required by MKOverlay protocol
@synthesize coordinate,
    boundingMapRect;

- (instancetype)initWithModel:(Model *)model {
    coordinate = CLLocationCoordinate2DMake(model.latitude, model.longitude);
    double radiusInPoints = MKMapPointsPerMeterAtLatitude(model.latitude) * model.radius;
    boundingMapRect = MKMapRectMake(model.latitude, model.longitude, radiusInPoints, radiusInPoints);
    return self;
}

@end

Вызывается mapView:rendererForOverlay, и, проверяя overlay в отладчике, я вижу coordinate в пределах текущих экранных границ карты и то, что кажется разумным boundingMapRect (хотя я не уверен, что такое «точки карты», я верю, что MKMapPointsPerMeterAtLatitude, чтобы делать то, что он говорит, что делает).

Но на карте не появляются многоугольники.


ОБНОВЛЕНИЕ:

Теперь я понимаю, что пытаюсь визуализировать полигоны, не создавая их. Таким образом, вместо CustomMapOverlay я теперь создаю MKPolygon оверлеев вроде этого:

CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(model.latitude, model.longitude);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(centerCoordinate, model.radius, model.radius);

int numCoords = 4;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numCoords);
coords[0] = CLLocationCoordinate2DMake((region.center.longitude - 0.5*region.span.longitudeDelta), (region.center.latitude + 0.5*region.span.latitudeDelta));
coords[1] = CLLocationCoordinate2DMake((region.center.longitude + 0.5*region.span.longitudeDelta), (region.center.latitude + 0.5*region.span.latitudeDelta));
coords[2] = CLLocationCoordinate2DMake((region.center.longitude + 0.5*region.span.longitudeDelta), (region.center.latitude - 0.5*region.span.latitudeDelta));
coords[3] = CLLocationCoordinate2DMake((region.center.longitude - 0.5*region.span.longitudeDelta), (region.center.latitude - 0.5*region.span.latitudeDelta));
MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coords count:numCoords];
free(coords);

[self.mapView addOverlay:polygon];

Однако теперь mapView:rendererForOverlay больше не получает вызова.


person ericsoco    schedule 16.04.2014    source источник


Ответы (1)


В обновленном коде, который создает MKPolygon, координаты в массиве coords обратны. Например, эта строка:

coords[0] = CLLocationCoordinate2DMake(
              (region.center.longitude - 0.5*region.span.longitudeDelta), 
              (region.center.latitude + 0.5*region.span.latitudeDelta));

должно быть:

coords[0] = CLLocationCoordinate2DMake(
              (region.center.latitude + 0.5*region.span.latitudeDelta,
              (region.center.longitude - 0.5*region.span.longitudeDelta));

В функции CLLocationCoordinate2DMake первым параметром является широта, затем долгота.


Поскольку координаты указаны в обратном порядке, они могут быть либо полностью неверными, либо находиться в неправильном месте.

Метод делегата rendererForOverlay будет вызываться только в том случае, если boundingMapRect наложения (который MKPolygon будет автоматически определять на основе заданных координат) находится в текущей отображаемой области карты. Но если координаты неверны или находятся в неправильном месте, boundingMapRect также будет недействительным.



Кстати, в исходном коде, который использовал CustomMapOverlay, были как минимум две проблемы:

  1. Метод initWithModel не вызывает [super init] (предполагается, что это подкласс NSObject).
  2. boundingMapRect рассчитывается неправильно. Функция MKMapRectMake принимает MKMapPoint значений, но код передает широту и долготу в градусах. MKMapPoint - это не то же самое, что CLLocationCoordinate2D. Вы можете преобразовать CLLocationCoordinate2D в MKMapPoint с помощью функции MKMapPointForCoordinate. См. MKMapPointForCoordinate, возвращающий недопустимые координаты и Сопоставьте системы координат в документации для получения дополнительной информации.
person Community    schedule 16.04.2014
comment
Я, должно быть, очень устал делать эту ошибку с долгосрочным долгом. Также полезно знать о назначении boundingMapRect. - person ericsoco; 17.04.2014